The lifetime-extension of a temporary object can be performed only once, when the temporary object gets bound to the first reference. After that, the knowledge that the reference refers to a temporary object is gone, so further lifetime extensions are not possible.
The case that is puzzling you
A const& refnop = A(a).nothing();
is similar to this case:
A const& foo(A const& bar)
{
return bar;
}
//...
A const& broken = foo(A());
In both cases, the temporary gets bound to the function argument (the implicit this
for nothing()
, bar
for foo()
) and gets its lifetime ‘extended’ to the lifetime of the function argument. I put ‘extended’ in quotes, because the natural lifetime of the temporary is already longer, so no actual extension takes place.
Because the lifetime extension property is non-transitive, returning a reference (that happens to refer to a temporary object) will not further extend the lifetime of the temporary object, with as result that both refnop
and broken
end up referring to objects that no longer exist.