2

I need a few clarification regarding const reference. From this link:

const Foo &myFoo = FuncBar();

const reference extended the life of the local object. But when I checked this link although they used a const reference

Sandbox(const string& n) : member(n) {}

the lifetime of string "four" did not increase.

Sandbox sandbox(string("four"));

They used the sentence

Only local const references prolong the lifespan.

Then in the second link isn't the string "four" local to the main function and shouldn't the const reference n prolong its life?
So why isn't the lifetime getting prolonged in the second link?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
user3762146
  • 205
  • 3
  • 13

2 Answers2

5

The two links which you have referred are different in the sense that one shows the use of a local const reference and other shows the use of a class member const reference.

When we create local const references and refer to a temporary object then in this compiler extends the life of the temporary till the scope of local const reference.

Class member const reference pointing to temporary will lead to unexpected results as the life of the temporary object will not be extended beyond the constructor invoked to initialize class member reference. As explained in one of the answers the temporary will only survive till completion of the constructor.

Quoting the answer from: Does a const reference prolong the life of a temporary?

The lifetime extension is not transitive through a function argument. §12.2/5 [class.temporary]:

The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object to a subobject of which the temporary is bound persists for the lifetime of the reference except as specified below. A temporary bound to a reference member in a constructor’s ctor-initializer (§12.6.2 [class.base.init]) persists until the constructor exits. A temporary bound to a reference parameter in a function call (§5.2.2 [expr.call]) persists until the completion of the full expression containing the call.

If you analyze it correctly you will realize that in both cases the life of temporary is extended till the scope from where the references are initialized is valid. As soon as the scope from where reference goes out of scope the temporary becomes invalid.

For local const reference, scope is inside a function from where it is being initialized to a temp. For class member const reference, scope is constructor where it is being initialized to a temp.

You should also read this GOTW article: https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

Community
  • 1
  • 1
Nik
  • 1,294
  • 10
  • 16
0

I feel like it's worth imagining what may be happening under the covers (in assembler/machine language) to help understand this behavior.

Parameters (either values or addresses of values) are passed into a function on the stack.

While a function is operating, local variables are pushed onto the stack, and operations involving those variables are done using an address that is relative to a register which got a copy of the value of (address pointed at by) the stack pointer as of the time when our function was called.

When a function exits, it "unwinds the stack," by moving the stack pointer back to the position that it was in before the parameters were pushed onto the stack, and then the return value(s) are pushed onto the stack.

So when we call a function, our locals are on the stack, and our parameters get pushed onto it after them. When the function returns, the return value is on the stack in place of our parameters right after our locals.

If we assign that return value to a local, the compiler may choose to do a bit of "return value optimization" in the form of "copy elision" by simply associating that stack location with that local.

This "copy elision" may be sort of "forced" or at least "requested" in the case where the return value is being assigned to a "const reference". But it's still a reference to a stack location - so when the function in which the function call was made returns... the stack is unwound and all the locals are lost including that return value.

In light of this.. intuitively imagined understanding of what's happening, it seems like C++ should allow local non-const references to be assigned to return values, but it should not allow non-local references (const or otherwise) to be assigned to return values, because assigning a non-local reference implies that the memory associated with that reference is somehow being preserved outside of the local scope without copying it, which, in the case of a return value stored on the stack, is rather impractical.

Shavais
  • 2,476
  • 1
  • 27
  • 25