Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is an argument copied to the resulting temporary when both the function parameter and return types are references?

Tags:

c++

Chapter 6.3.2 of the book C++ Primer says the following:

The return value is used to initialize a temporary at the call site, and that temporary is the result of the function call.

Later, it gives an example for returning reference values with the explanation below:

const string &shorterString(const string &s1, const string &s2)
{
    return s1.size() <= s2.size() ? s1 : s2;
}

The parameters and return type are references to const string. The strings are not copied when the function is called or when the result is returned.

Does this mean that the temporary resulting from this function call is initialized from a reference to the first or the second argument? If so, doesn't that mean that the argument does get copied into the temporary?

like image 766
L.S. Roth Avatar asked Jul 31 '20 18:07

L.S. Roth


2 Answers

Does this mean that the temporary resulting from this function call is initialized from a reference to the first or the second argument?

Yes.

As the logic in the function suggests, wether the temporary is initialized from the first argument or the second argument depends on the value of s1.size() <= s2.size().

If so, doesn't that mean that the argument does get copied into the temporary?

Yes.

However, it's worth noting that the temporary itself is also a const string&. It does not require a copy of a string object.

like image 127
R Sahu Avatar answered Oct 21 '22 17:10

R Sahu


The return value is used to initialize a temporary at the call site, and that temporary is the result of the function call.

The use of "temporary" is a bit misleading, and as of C++17 - false.

Up until C++17, the function could theoretically have created a temporary which is the return value. But the compiler was allowed to skip the creation of such a temporary, and just initialize/construct at the call site, e.g. if you wrote:

const std::string& foo { shorterString(my_string1, my_string2) };

then foo would have been initialized by the code inside shorterString directly (even if the function wasn't inlined). Granted, this doesn't matter all that much for const std::string&, but it sure does matter for types whose construction has side-effects; and for types which are non-copyable/non-movable.

Beginning in C++17, this is no longer an "optimization" - it is guaranteed in the standard that no temporary is constructed/initialized. See this blog post for a detailed discussion.

like image 1
einpoklum Avatar answered Oct 21 '22 18:10

einpoklum