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);