other is a reference. If f() returns a reference you'll need to be careful when using other so that the object that the reference refers is still alive.
what happens if f() does not return a reference? is other valid?
A temporary object is created (via "temporary materialization") and the reference binds it.
The lifetime of the temporary is then extended to match the lifetime of the reference, so the reference continues to refer to a valid thing until its own lifetime is over.
#include <iostream>
int& f()
{
int value=5;
return value;
}
int main()
{
int& ret = f();
std::cout << ret << '\n';
ret = 42;
int two = f();
std::cout << ret << '\n';
}
on cpp.sh and got:
main.cpp:7:12: warning: reference to stack memory associated with local variable 'value' returned [-Wreturn-stack-address]
and the output:
5
5
So the memory on stack was overwritten (by second call to f() ).
#include <iostream>
int& f()
{
int value=5;
return value;
}
int g()
{
int val=7;
return val;
}
int main()
{
int& ret = f();
std::cout << ret << '\n';
ret = 42;
int two = g();
std::cout << ret << '\n';
}
No, lifetime extension only apply when you bind it directly to the temporary. My mental model is that the reference needs to be a local variable (or global) but I'm not sure what the standard actually says about struct members and there might be other corner cases. Whether lifetime extension applies to function argument is not something worth thinking about because the temporary is guaranteed to live for as long as the parameter is in use even without lifetime extension because it's not destroyed until after the function returns.
I had to look this one up. && is specifically a reference to a rvalue, usually a temporary and most of the examples bind to results of computations (eg a reference to (x+y). It is a special syntax just for that purpose alone. & is now being called an lvalue reference, which should not be applied to temporary objects.
I agree you have UB there. g() should not change ret, but it does, probably because your & reference bound it to a memory location that was reused, probably because f and g are virtually identical signatures so the placement of their local val variables will be in the same spot.
I think the point is that had you used && instead, it should have worked as expected. You must remove the & off f() to make it work, allowing it to bind.
#include <iostream>
int f()
{
int value=5;
return value;
}
int g()
{
int val=7;
return val;
}
int main()
{
int&& ret = f();
std::cout << ret << '\n';
ret = 42;
int two = g();
std::cout << ret << '\n';
}