DarkZeros DarkZeros - 2 months ago 6
C++ Question

Initializing a std::string with function return value, is there a copy?

I have the following code, I am using GCC and C++11:

std::string system_call(const char *cmd){
std::string a;
...
return a;
}

std::string st = system_call("whatever code");


Is there an implicit copy there?
I am calling this function many times, and I guess it is doing a copy from the return value of the
system_call
to the variable
st
, and later on releasing the temporary r-value.

Is there any way I can avoid the copy? Using
st.swap(system_call())
throws and error in the compiler:


error: no matching function for call to
'std::basic_string::swap(std::string)'


My questions are:


  1. If there is a problem or not

  2. How to avoid it, if there is one



Thanks

EDIT:
Found a way to make the explicit swap work. But the answers where right, there is no benefit since the compiler was already replacing st with the return value, without any copy.

system_call("whatever").swap(st);

Answer

In general, if the std::string is constructed in the call and then returned most modern compilers with apply the return value optimization (a special case of copy elision). Your case in particular is the Named RVO (thanks @NathanOliver for pointing this out), if you want to look up the precise rules. From C++17 on this optimization is guaranteed through the standard.

Whether or not the optimization is applied is hard to tell, however if it is not, then in C++11 and above it is very likely that the std::string object in the scope of the function will be moved from and that the return value will be moved to. You could theoretically call std::move on the return value, but thereby you would also prevent any RVO from happening. While move may be efficient, RVO typically yields faster code, because nothing is moved or copied at all, but the object is constructed in place, so I would advise against doing it, and in favor of relying on your compiler.

Comments