So, is the int_ref creating a new memory space, copying by value and then attaching a reference? Or is it actually referencing to the variable a(inside return_int_ref).
Can't we just do int int_ref { return_int_ref() }; , and make others take reference of it? Isn't this the same thing??
You call function return_int_ref(). When a function is called, space is allocated from stack for the parameters, return value and local automatic variables of the function.
This function has one int local variable (a) and int return value. I can't tell whether compiler optimizes those to one int (and thus avoids copy from 'a' to return value). Memory for at least one int is definitely allocated. Lets call it UT (unnamed temporary).
The main() thus has a line: constint& int_ref { UT };
where the reference int_ref is bound to UT.
Due to the const reference the lifetime of UT extends beyond this statement (like UT were automatic variable in the scope of function main() ).
Yes, the compiler sometimes will extend the lifetime of a temporary, but you should only rely on such an esoteric feature when you absolutely must, and then, you should have plenty of comments explaining what's going on.
As a new C++ programmer, there are many other features that you should worry about before this one.
@kekiverto Thank you for the amazing explanation.
But I tried checking the memory location of both, and they're different. How does this theory hold against that? e.g. I tried printing out memory location of:
local variable(a) 0x7ffed98ed604
int_ref 0x7ffed98ed62c.
If int_ref is indeed referring to the UT, then the value should've been same shouldn't it ? Or is it that my compiler is returning a copy of a and int_ref is storing THAT address?.
Appreciate your patience !
@dhyaden
Thanks for the reply, I think I came out to be more modest then I thought when I said I'm a newb in C++
@dutch
Thanks for the reply !. So, you're implying my first assumption is correct? ( initializing and then attaching reference ?).
Once return_int_ref() is executed all its local variables are destroyed, the return value which int_ref gets is stored in a const variable. So it isn't "extending" lifetime of that object per se, its just copy of the return value?
That depends on what you mean by "attaching reference".
I'm saying that there is no "reference" in the normal sense.
There is no hidden pointer variable pointing to a memory location holding the value.
Instead, int_ref becomes just a simple (const) int.
Note that in your example, 'a' (or it's address) has nothing to do with it. Only it's value is returned from the function.
And, no, there is no way of "extending" the lifetime of a local variable.
By definition, a local variable is stored on the stack, and you know the problem with that.
It's storage must exist somewhere else (like on the caller's stack frame or the heap) if it is to be referenced after the function ends.
The generated code doesn't necessarily align perfectly with C++'s object model.
Conceptually, there is lifetime extension going on, but not of a local variable. The temporary object whose lifetime is extended is the result of the temporary materialization conversion from the prvalue expression return_int_ref()
To an xvalue denoting the resulting temporary.
Ordinarily, that temporary would exist until the semicolon (i.e., until the evaluation of the full-expression is complete). But because the temporary is bound to a reference to const, its lifetime is extended to match the lifetime of the reference.
(Despite the misleading name, the expression return_int_ref() is actually a prvalue expression -- return_int_ref has a return type of int).
One last thing, I've read that using const auto& ref to some value returning function in a for-loop saves one instantiation, something related to "saves time of ctor"
e.g. get_class_obj returns a very class object
apparently this is more efficient in space/time ?(don't exactly know which, I'd be glad if you vividly explain that)
for(int i =0 ; i < 4 ; i++){
cont auto& ref = get_class_obj();
fun(ref);
}
than
for(int i =0 ; i<4 ; i++)
{
auto val = get_class_obj();
fun(ref);
}
where fun(const A&). In this context , I think both ref and val are no different inside fun() and possibly achieve this with same efficiency. (Which I want to clarify)
I understand it's going a little off-topic but this was the actual reason I posted and I'd be glad if you can clear this for me. Thanks for everything till now!