71

Possible Duplicate:
Does a const reference prolong the life of a temporary?

My compiler doesn't complain about assigning temporary to const reference:

string foo() {
  return string("123");
};

int main() {
  const string& val = foo();
  printf("%s\n", val.c_str());
  return 0;
}

Why? I thought that string returned from foo is temporary and val can point to object which lifetime has finished. Does C++ standard allow this and prolongs the lifetime of returned object?

Community
  • 1
  • 1
gruszczy
  • 40,948
  • 31
  • 128
  • 181
  • 4
    Yes, the temporary's lifetime is prolonged as long as it's a **const** reference. – chris Jul 19 '12 at 11:56
  • 4
    That's not exactly a duplicate of 2784262, which (should) treat the case where the reference is a class member. The behavior is different. – aberaud Nov 29 '14 at 20:54
  • 2
    @aberaud not only this is not a duplicate, it is a much better question I am glad I found. – dashesy Jul 01 '16 at 14:30

1 Answers1

89

This is a C++ feature. The code is valid and does exactly what it appears to do.

Normally, a temporary object lasts only until the end of the full expression in which it appears. However, C++ deliberately specifies that binding a temporary object to a reference to const on the stack lengthens the lifetime of the temporary to the lifetime of the reference itself, and thus avoids what would otherwise be a common dangling-reference error. In the example above, the temporary returned by foo() lives until the closing curly brace.

P.S: This only applies to stack-based references. It doesn’t work for references that are members of objects.

Full text: GotW #88: A Candidate For the “Most Important const” by Herb Sutter.

Sergey K.
  • 24,894
  • 13
  • 106
  • 174
  • 2
    Also, please notice that through no copy is done on the string here, a copy constructor for string must exists and be accessible. – xryl669 Nov 25 '13 at 16:53
  • 1
    re the **P.S**, this is very important, and the dupe SO thread linked above has good illustrations of this – underscore_d Mar 06 '16 at 02:27
  • @xryl669 Does [c++17 Guaranteed copy elision](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html) mean copy constructor is no longer necessary? quote: ``` when the source object is a temporary ``` – dashesy Jul 01 '16 at 15:09
  • @dashesy What do you mean? A copy constructor was _never_ "necessary" in such cases. In practice, if the `return` expression of `f()` returned an unnamed _rvalue_, RVO would almost certainly have kicked in and elided the copy construction, instead directly constructing the returned object in the caller's receiving location (variable). Had the `return` expression returned a named object, NRVO might've done the same. What C++17's guaranteed copy elision achieves is to _require_ elision in the former, simpler case of RVO. – underscore_d Aug 14 '16 at 16:46
  • @underscore_d yes, no copy is made but xryl669 comment states that still a copy constructor was needed. – dashesy Aug 15 '16 at 15:17
  • 1
    @dashesy Oops, I get it now. Fair question. And thankfully the answer is trivial to find: http://stackoverflow.com/a/38043447/2757035 That's a _yes_. It follows logically from the _guaranteed_ part of the name. If copy elision is guaranteed, then there doesn't need to be an accessible copy or move constructor, for it is guaranteed _not_ to ever be needed. – underscore_d Aug 15 '16 at 17:27