Pass by value or const reference to function?

2019-06-28 01:51发布

问题:

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

回答1:

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 :)



回答2:

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?



回答3:

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)


回答4:

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:

  • What's the difference between passing by reference vs. passing by value?
  • Is it better in C++ to pass by value or pass by constant reference?
  • Dave Abrahams - Want Speed? Pass by Value
  • What are move semantics?
  • Why is value taking setter member functions not recommended in Herb Sutter's CppCon 2014 talk (Back to Basics: Modern C++ Style)?