2

Suppose that a function has the signature

std::string GetString();

and that it returns a new string by value. Now given the following code:

// (a) Store the return value to a const reference.
const std::string& my_string = GetString();

// (b) Store the return value to a (const) value.
const std::string my_string = GetString();

Am I correct to understand that (a) and (b) are, from a C++11 compiler's point of view, identical? If so, is there a rough consensus on the choice of style?

Jae Heon Lee
  • 1,101
  • 6
  • 10
  • I would be surprised if they were identical. In the case b, you actually have a std::string. In case a, you have a reference to a string, but no actual std::string storage. It should crash, or perhaps even fail to compile. – Chris Becke Nov 03 '15 at 06:18
  • @ChrisBecke [This Q&A](http://stackoverflow.com/questions/2784262/does-a-const-reference-prolong-the-life-of-a-temporary) explains the case (a). – Jae Heon Lee Nov 03 '15 at 06:50

2 Answers2

1

Am I correct to understand that (a) and (b) are, from a C++11 compiler's point of view, identical?

No, they are not identical.

(a) extends the life of the temporary object returned by GetString().

(b) makes a new object. It is constructed by:

  1. invoking the copy constructor of std::string by using the return value of GetString() as the argument,
  2. being assigned the return value of GetString() by RTO, or
  3. invoking the move constructor using the return value of GetString().
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • A couple nits: (a) doesn't "extend the life of the temporary". The temporary created by the return value of `GetString` is gone and (a) is a reference to a temporary that no longer exists. (b) may or may not invoke the copy constructor due to the return value optimization (since forever) or due to move semantics (C++11 or later) where the value constructed by `GetString()` is directly moved into the storage declared in (b) without invoking the copy constructor. – legalize Nov 03 '15 at 16:18
  • 1
    @legalize, agree with you on (b), not on (a). See [Does a const reference prolong the life of a temporary?](http://stackoverflow.com/questions/2784262/does-a-const-reference-prolong-the-life-of-a-temporary) – R Sahu Nov 03 '15 at 16:29
  • @R Sahu OK, I see your point about (a). However, this feels like an edge condition that is harder to remember than it is to avoid. The return value optimization/move semantics comes up much more often and is more useful to understand IMO. – legalize Nov 03 '15 at 20:17
  • 1
    @legalize, it's a feature of the language that is useful when you need to simply query the returned object for useful information. The type - `const&` - should be a clear reminder of the purpose of the object. – R Sahu Nov 03 '15 at 20:22
  • 1
    @legalize reference binding is very common in C++ and essential to understand. Actually all references (i.e. rvalue references also) extend lifetime of a temporary if they are legally bound – M.M Nov 03 '15 at 20:29
  • @M.M I understand references and how they bind. However, in 20 years of C++ programming I can't say that the **lifetime extension** property of references has come up as something that you need to know about on a daily basis. Now that we're discussing it, this bit of esoterica feels familiar, but as I say I just don't see memorizing it as something that is coming up every day. – legalize Nov 03 '15 at 21:06
0

Theoretically they are different, but practically they are identical. The only code you can write to tell the difference would involve decltype(my_string).

The compiler could generate the same assembly for both.

M.M
  • 138,810
  • 21
  • 208
  • 365