C++ - using const reference to prolong a member of a temporary, ok or UB?
Your code should be well-formed, because for temporaries
(emphasis mine)
Whenever a reference is bound to a temporary or to a subobject thereof, the lifetime of the temporary is extended to match the lifetime of the reference
Given A().b[4]
, b[4]
is the subobject of b
and the data member b
is the subobject of the temproray A()
, whose lifetime should be extended.
LIVE on clang10 with -O2
LIVE on gcc10 with -O2
BTW: This seems to be a gcc's bug which has been fixed.
From the standard, [class.temporary]/6
The third context is when a reference is bound to a temporary object.36 The temporary object to which the reference is bound or the temporary object that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference if the glvalue to which the reference is bound was obtained through one of the following:
...
[ Example:
template<typename T> using id = T; int i = 1; int&& a = id<int[3]>{1, 2, 3}[i]; // temporary array has same lifetime as a const int& b = static_cast<const int&>(0); // temporary int has same lifetime as b int&& c = cond ? id<int[3]>{1, 2, 3}[i] : static_cast<int&&>(0); // exactly one of the two temporaries is lifetime-extended
— end example ]
A().b[4]
is not a temp or rvalue, which is why it does not work. Whilst A()
is a temporary, you are creating a reference to an array element that exists at the point of creation. The dtor then triggers for A()
, which means the later access to b.b
becomes somewhat undefined behavior. You'd need to hold onto the A&
to ensure b
remains valid.
const A& a = A();
const B& b = a.b[4];
C c(b.x, b.y);