¿Es legal" rebinding " referencias en C++ como este?


¿ Es legal lo siguiente en C++?

Por lo que puedo decir, Reference tiene un destructor trivial, por lo que debería ser legal.
Pero pensé que las referencias no pueden ser rebotadas legalmente... pueden?

template<class T>
struct Reference
{
    T &r;
    Reference(T &r) : r(r) { }
};

int main()
{
    int x = 5, y = 6;
    Reference<int> r(x);
    new (&r) Reference<int>(y);
}
Author: templatetypedef, 2014-01-14

3 answers

Creo que encontré la respuesta en un pasaje debajo de el "citado" que habla de efectos secundarios triviales de dtor / dtor, a saber [básico.vida] / 7:

Si, una vez finalizada la vida útil de un objeto y antes de que se reutilice o libere el almacenamiento que ocupa el objeto, se crea un nuevo objeto en la ubicación de almacenamiento que ocupa el objeto original, un puntero que apunta al objeto original, una referencia que hace referencia al objeto original, o el nombre objeto original se referirá automáticamente al nuevo objeto y, una vez que la vida útil del nuevo objeto ha comenzado, puede se utilizará para manipular el nuevo objeto, si:

  • El almacenamiento del nuevo objeto se superpone exactamente a la ubicación de almacenamiento que ocupaba el objeto original, y

  • El nuevo objeto es del mismo tipo que el objeto original (ignorando los calificadores cv de nivel superior), y

  • El tipo del objeto original no es const-qualified, y, si es un tipo de clase, no contiene ningún miembro de datos no estático cuyo tipo está const-qualified o un tipo de referencia, y

  • El objeto original era un objeto más derivado de tipo T y el nuevo objeto es un objeto más derivado de tipo T (es decir, no son subobjetos de clase base).

Al reutilizar el almacenamiento, terminamos la vida útil del objeto original [basic.life] / 1

La vida útil de un objeto de tipo T termina cuando:

  • Si T es un tipo de clase con un destructor no trivial, se inicia la llamada a destructor, o

  • El almacenamiento que ocupa el objeto se reutiliza o libera.

Así que pienso [básico.life] / 7 cubre la situación

Reference<int> r(x);
new (&r) Reference<int>(y);

Donde finalizamos la vida útil del objeto denotado por r, y creamos un nuevo objeto en la misma ubicación.

Como Reference<int> es un tipo de clase con un miembro de datos de referencia, el requisitos de [basic.la vida] / 7 no se cumplen . Es decir, r podría ni siquiera referirse al nuevo objeto, y no podemos usarlo para "manipular" este objeto recién creado (interpreto este "manipular" también como accesos de solo lectura).

 4
Author: dyp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-15 20:08:36

No volver a enlazar una referencia, está creando un nuevo objeto en la memoria de otro con una ubicación nueva. Dado que el destructor del viejo objeto nunca se ejecutó, creo que este sería un comportamiento indefinido.

 18
Author: Mark Ransom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-13 21:40:59

No hay ninguna referencia de rebote en tu ejemplo. La primera referencia (construida en la línea dos con el nombre r.r) está vinculada a la int denotada por x durante toda su vida. El tiempo de vida de esta referencia termina cuando el almacenamiento para su objeto contenedor es reutilizado por la nueva expresión de colocación en la línea tres. El objeto de reemplazo contiene una referencia que está enlazada y durante toda su vida útil que dura hasta el final de su alcance - el final de main.

 11
Author: CB Bailey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-13 21:52:43