Passing std::string by Value or Reference

138,349

Solution 1

There are multiple answers based on what you are doing with the string.

1) Using the string as an id (will not be modified). Passing it in by const reference is probably the best idea here: (std::string const&)

2) Modifying the string but not wanting the caller to see that change. Passing it in by value is preferable: (std::string)

3) Modifying the string but wanting the caller to see that change. Passing it in by reference is preferable: (std::string &)

4) Sending the string into the function and the caller of the function will never use the string again. Using move semantics might be an option (std::string &&)

Solution 2

Check this answer for C++11. Basically, if you pass an lvalue the rvalue reference

From this article:

void f1(String s) {
    vector<String> v;
    v.push_back(std::move(s));
}
void f2(const String &s) {
    vector<String> v;
    v.push_back(s);
}

"For lvalue argument, ‘f1’ has one extra copy to pass the argument because it is by-value, while ‘f2’ has one extra copy to call push_back. So no difference; for rvalue argument, the compiler has to create a temporary ‘String(L“”)’ and pass the temporary to ‘f1’ or ‘f2’ anyway. Because ‘f2’ can take advantage of move ctor when the argument is a temporary (which is an rvalue), the costs to pass the argument are the same now for ‘f1’ and ‘f2’."

Continuing: " This means in C++11 we can get better performance by using pass-by-value approach when:

  1. The parameter type supports move semantics - All standard library components do in C++11
  2. The cost of move constructor is much cheaper than the copy constructor (both the time and stack usage).
  3. Inside the function, the parameter type will be passed to another function or operation which supports both copy and move.
  4. It is common to pass a temporary as the argument - You can organize you code to do this more.

"

OTOH, for C++98 it is best to pass by reference - less data gets copied around. Passing const or non const depend of whether you need to change the argument or not.

Solution 3

I believe the normal answer is that it should be passed by value if you need to make a copy of it in your function. Pass it by const reference otherwise.

Here is a good discussion: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

Share:
138,349
Nordlöw
Author by

Nordlöw

Have worked with Simulators and Signal and Image Processing. Fluent in D, C, C++, Python and MATLAB. Have worked with Boost, Armadillo, FFTW, OpenCV. Have developed for Linux and Windows.

Updated on March 06, 2020

Comments

  • Nordlöw
    Nordlöw about 4 years

    Possible Duplicate:
    Are the days of passing const std::string & as a parameter over?

    Should I pass std::string by value or by reference (to a un-inlined function) if move semantics is supported? And what about implementations using small string optimization (SSO)?

  • Nordlöw
    Nordlöw almost 12 years
    Case 3) is only neccessary if the std::string implementation doesn't support move semantics right?
  • linuxuser27
    linuxuser27 almost 12 years
    @Nordlöw Not really. Move semantics are interesting because they are moving the data not copying it. In the above case the move semantics would move the char * in the std::string from the caller function to the called function. If you use move semantics to pass in the value the string will no longer be in the caller function unless you pass it back out. See the link above talking about move semantics.
  • Benjamin Lindley
    Benjamin Lindley almost 12 years
    #4 is unnecessary, as this is something that can and should be taken care of on the caller's side by using std::move on his argument and invoking the by-value version.
  • Destructor
    Destructor over 8 years
    @BenjaminLindley: See ideone.com/OYu0Ux . What happens when I directly pass string literals to function that has arguments of type const std::string&. Does the compiler create 2 temporary std::string objects & bind that to two const reference parameters respectively behind the scenes for rvalues?
  • emlai
    emlai about 8 years
    @BenjaminLindley Not at all, && prevents accidentally passing the argument by copy.
  • emlai
    emlai about 8 years
    @Destructor It constructs a std::string from the string literal and passes it as an argument. Then it copy constructs the member string from the argument. So two allocations and two O(n) array copy operations (per argument). You should take the params by value and std::move them into the members. That way it would be only one allocation, one O(n) array copy, and one O(1) move per argument.
  • DanielTuzes
    DanielTuzes over 4 years