4

Should I pass std::string by value or by reference to one function. This function store this values in member variable of class.

I am always confuse when about pass by value or reference. Please clear my confusion about this.

Here is code :

class DataStore {
public:
    void addFile(const string& filename, const set< std::string>& filePaths)
    {  
        if (dataStoreMap.insert(make_pair(filename, filePaths)).second)
        {
            cout << "Data Added" <<endl;
        }
        else
        {
            cout << "Data not Added" << endl;
        }
    }
private:
    // member variable
    map < string, set < string >  > dataStoreMap;
};

Shall I make function declaration like this :

void addFile(const string& filename, const set< std::string>& filePaths)

or

void addFile(const string filename, const set< std::string> filePaths)

Both gives same result. If there any issue about memory allocation or performance.

Above function call from cpp class.

DataStore ds;
set<string> setFileDirectory{ "1", "2", "3", "4", "6", "5" };
ds.addFile("file.txt", setFileDirectory);

setFileDirectory.erase(setFileDirectory.begin(), setFileDirectory.end());
setFileDirectory.insert({ "1", "2", "3", "4", "5", "6" });
ds.addFile("demo.txt", setFileDirectory);

Any detailed explanation would be appreciated.

Thanks

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
sam_k
  • 5,983
  • 14
  • 76
  • 110
  • Thanks a lot for your reply. I understand what you mean but when i have to use value or ref. that is still confusing for me. Here i am going to store values in map so pass by value is good thing? or Pass by ref? – sam_k Jan 29 '15 at 00:08
  • Is your question what the difference between passing by value and passing by reference is? – IllusiveBrian Jan 29 '15 at 00:19
  • @Namfuak : Confusion between when to use pass by ref or pass by value. – sam_k Jan 29 '15 at 00:21

4 Answers4

3

When you have an input parameter, i.e. something that is observed by the function and not modified, consider passing it by const reference (const &), to avoid useless deep-copies (which may require dynamic memory allocations, etc.)

void addFile(const std::string& filename, 
             const std::set<std::string>& filePaths)

P.S.
Of course, if you are passing parameters that are cheap to copy, like ints, you can just pass by value :)

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
  • Thanks a lot for your reply. I understand what you mean but when i have to use value or ref. that is still confusing for me. Here i am going to store values in map so pass by value is good thing? or Pass by ref? – sam_k Jan 29 '15 at 00:22
  • @Sam_k: Please keep two aspects distinct: what you store in the map (or other containers), and what you pass to the function as parameters. My answer focuses on what to pass as parameters, and I won't repeat my answer in this comment. Instead, about storing stuff in containers, in general storing values is a good choice: it makes deep-copies of the values, so they are "physically" contained in the container, and decoupled from other external contexts (this also simplifies ownership, lifetime management, etc.). – Mr.C64 Jan 29 '15 at 23:05
0

If your container set has a huge size and passing string to function is comparatively small I may use as follows:

void addFile(const string filename, const set< std::string> & filePaths)
Steephen
  • 14,645
  • 7
  • 40
  • 47
  • 1
    [`insert`](http://en.cppreference.com/w/cpp/container/set/insert) returns a `pair`, the second element being true if the insertion was successful and false if not, which seems like what he intended to check. Why do you think it is wrong? – IllusiveBrian Jan 28 '15 at 23:59
  • Its right. I am checking true or false which is return by insert function – sam_k Jan 29 '15 at 00:06
0

The first has "better" performance, because the second makes a copy of the string before passing it. Since you aren't modifying the string, there is no downside passing a reference to the actual string in the calling function rather than making a copy, and takes less memory to copy a reference than a string. That said, the compiler may end up treating them equivalently if you never cast off the const specifier on the string variable. This difference is more useful on large parameters, for example if your filepaths variable had a few thousand elements there may be a very noticeable difference in passing it by reference rather than by value.

Related: Is it better in C++ to pass by value or pass by constant reference?

Community
  • 1
  • 1
IllusiveBrian
  • 3,105
  • 2
  • 14
  • 17
0

First of all, you should never pass arguments by const value as there's hardly any reason for it. Passing by value already makes sure you can not alter the variable at the call site as it is copied.

Now, the question still remains about passing arguments by value or reference. And the answer is more complicated than could be expected. There are a lot of good answers written about this on Stack Overflow.

In short, when passing potentially large objects (like std::vector or std::string) to functions use these idiomatic guidelines:

  • When passing for observation (read only) pass by reference to const.
  • When passing an argument that you want to retain a copy of (so called sink argument), then also pass by reference to const. If the passed object is movable you can also add an overload taking the argument by rvalue reference (T&&) for optimization.

Related info:

Community
  • 1
  • 1
Felix Glas
  • 15,065
  • 7
  • 53
  • 82
  • 2
    "here's hardly any reason for it (except for built-in types)" What's the exception for built-in types? – Neil Kirk Jan 29 '15 at 00:59
  • @NeilKirk Well IMO sometimes it can be practical to use e.g. `const int` for a number you don't want modified inside the function (it only adds value to the implementer). Still I removed that part as my argument is a bit weak :) – Felix Glas Jan 29 '15 at 01:05