son siguientes ruta predeterminada por pat pasos para necesarios los funciona defecto cuáles configurar como c++ reference language-lawyer c++14

c++ - siguientes - Referencia de enlace a un objeto antes de la construcción



ruta predeterminada cisco (2)

[...] no hay mención de referencias en el ejemplo [...]

Quieres decir, excepto por

[...] refiriéndose a cualquier miembro no estático [...]

Del pasaje que citas, diría que esta línea provoca un comportamiento indefinido:

int& r3 = yobj.i; // #3

porque tú eres:

[...] refiriéndose a cualquier miembro no estático o clase base del objeto antes de que el constructor comience la ejecución [.]

Además, para esto:

y lo más importante, el párrafo anterior no implica que, de lo contrario, el comportamiento esté bien definido.

Tienes razón, no es así:

Se puede esperar un comportamiento indefinido cuando esta Norma Internacional omite cualquier definición explícita de comportamiento o cuando un programa utiliza una construcción errónea o datos erróneos.

¿Está bien definido el comportamiento del siguiente código?

struct X { int i; }; // trivial struct Y : X { Y(){} }; // non-trivial extern X xobj; int& r1 = xobj.i; // #1 X xobj; extern Y yobj; Y& r2 = yobj; // #2 // int& r3 = yobj.i; // #3 - this is UB according to the standard Y yobj;

Este código está inspirado en el ejemplo del estándar C ++, a saber, el borrador N4140 [class.cdtor] / 1.

Eso es lo que dice el párrafo:

Para un objeto con un constructor no trivial, hacer referencia a cualquier miembro no estático o clase base del objeto antes de que el constructor comience la ejecución da como resultado un comportamiento indefinido. Para un objeto con un destructor no trivial, hacer referencia a cualquier miembro no estático o clase base del objeto después de que el destructor finalice la ejecución da como resultado un comportamiento indefinido.

A continuación, se muestra un ejemplo que muestra cómo los punteros pueden y no estar vinculados a los objetos.

Intuitivamente, parece que #1 y #2 están bien definidos, mientras que #3 invoca a UB si no está comentado, pero, primero, los ejemplos no son normativos, segundo, no hay mención de referencias en el ejemplo, y tercero y el más importante, el párrafo anterior no implica que de lo contrario el comportamiento está bien definido. O lo hace? ¿O tal vez hay otra cita relevante en el estándar que me perdí?

Editar : La respuesta puede (posiblemente) ser sí si los objetos tienen una duración de almacenamiento estática, pero también pueden ser locales, por ejemplo:

struct A { A(){} }; struct B { B(A&){} }; struct C { B b; A a; C() : b(a) {} }; int main() { C c; }

En realidad, esta fue la inspiración inicial para esta pregunta, consulte Dependencia circular en la lista de inicialización del constructor


El comportamiento de # 2 definitivamente está bien definido. Como lo menciona @dyp, el párrafo relevante está en [basic.life]:

El enlace del glvalue yobj a una referencia está bien, ya que su almacenamiento dura toda la duración del programa ([basic.stc.static] / 1) y la referencia está vinculada a un objeto válido - aliveness a un lado - que cumple con el requisito en ( [dcl.ref] / 5). De forma similar, para el segundo ejemplo que mostró, siempre que no se realice ninguna operación en miembros del subobjeto A , el párrafo anterior también se aplica puesto que se llama al constructor de C en el almacenamiento asignado al que se refiere.