c++ language-lawyer lifetime temporary reference-binding

C++: ¿utiliza la referencia constante para prolongar un miembro de un temporal, ok o UB?



language-lawyer lifetime (2)

A (). B [4] no es una temp o rvalue, razón por la cual no funciona. Si bien A () es temporal, está creando una referencia a un elemento de matriz que existe en el punto de creación. El dtor luego se dispara para A (), lo que significa que el acceso posterior a bb se convierte en un comportamiento algo indefinido. Tendría que aferrarse a A y para asegurarse de que b siga siendo válido.

const A& a = A(); const B& b = a.b[4]; C c(b.x, b.y);

considera algo como esto:

#include <iostream> struct C { C(double x=0, double y=0): x(x) , y(y) { std::cout << "C ctor " << x << " " <<y << " " << "/n"; } double x, y; }; struct B { B(double x=0, double y=0): x(x), y(y) {} double x, y; }; struct A { B b[12]; A() { b[2] = B(2.5, 14); b[4] = B(56.32,11.99); } }; int main() { const B& b = A().b[4]; C c(b.x, b.y); }

cuando compilo con -O0 obtengo la impresión

C ctor 56.32 11.99

pero cuando compilo con -O2 obtengo

C ctor 0 0

Sé que podemos usar la referencia constante para prolongar un temporal local, así que algo como

const A& a = A(); const B& b = a.b;

Sería perfectamente legal. pero estoy luchando por encontrar el razonamiento de por qué el mismo mecanismo / regla no se aplica a ningún tipo de temporal

EDITAR PARA FUTURA REFERENCIA:

Estoy usando gcc versión 6.3.0


Su código debe estar bien formado, porque para los temporaries

(énfasis mío)

Cada vez que una referencia está vinculada a un temporal o a un subobjeto del mismo, la vida útil del temporal se extiende para que coincida con la vida útil de la referencia

Dado A().b[4] , b[4] es el subobjeto de b y el miembro de datos b es el subobjeto de la matriz A() , cuya vida útil debe extenderse.

EN VIVO en clang10 con -O2
EN VIVO en gcc10 con -O2

Por cierto: esto parece ser un bug de gcc que se ha solucionado.

Del estándar, [class.temporary]/6

El tercer contexto es cuando una referencia está vinculada a un objeto temporal. 36 El objeto temporal al que está vinculada la referencia o el objeto temporal que es el objeto completo de un subobjeto al que está vinculada la referencia persiste durante toda la vida útil de la referencia si el valor gl al que está vinculada la referencia se obtuvo a través de uno de los siguiendo:

...

[Ejemplo:

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

- ejemplo final]