teorico programas practico ejemplos completo codigo clases c++ initialization

c++ - programas - En la lista de inicialización de miembros, ¿puedo crear una referencia a una variable miembro que no esté en la lista?



ejemplos de programas en c++ pdf (3)

Considerar:

#include <string> #include <iostream> class Foo { public: Foo( char const * msg ) : x( y ) { y = msg; } std::string const & x; private: std::string y; }; int main( int argc, char * argv[] ) { if ( argc >= 2 ) { Foo f( argv[1] ); std::cout << f.x << std::endl; } }

Esto compila e imprime el primer parámetro ... pero tengo dudas de si realmente es "legal" / está bien formado. Sé que la lista de inicializadores debería inicializar las variables en orden de su declaración en la clase, para que no haga referencia a las variables que aún no se hayan inicializado. Pero ¿qué pasa con las variables miembro que no están en la lista de inicializadores ? ¿Puedo crear referencias a ellos de forma segura como se muestra?

(El ejemplo es, por supuesto, sin sentido. Es solo para aclarar de lo que estoy hablando).


¿Puedo crear referencias a ellos de forma segura como se muestra?

Sí tu puedes. La dirección de almacenamiento del miembro y se conoce independientemente de si la inicializó o no, por lo que la inicialización de referencia x(y) es legal.


Pero ¿qué pasa con las variables miembro que no están en la lista de inicializadores?

Si las variables están en la lista de inicializadores o no, es irrelevante a este respecto. Si una variable no está en la lista de inicializadores (ni tiene un inicializador de miembro predeterminado), entonces se inicializa por defecto.

y se inicializa después de x . Esto no se debe a la lista de inicialización de miembros, porque la lista de inicializadores de miembros no afecta el orden de inicialización de los miembros. Los miembros se inicializan en el orden de su declaración.

Sin embargo, si y es inicializado o no es también irrelevante. Está bien formado para enlazar una referencia a un miembro antes de que el miembro se inicialice (excepto el enlace a una base virtual de un miembro no inicializado; eso tendría UB).

En lo que respecta a la seguridad (o tal vez con mayor precisión), le recomiendo que se tome un tiempo para considerar qué sucede cuando se copia Foo . ¿A qué se referirá x ? ¿Es eso lo que el usuario de la clase esperaría?


Puedes hacerlo 1 porque:

  1. y están ya en el alcance ( [basic.scope.class]/1 ).
  2. Ya que está obteniendo una referencia después de que el constructor comenzó a ejecutarse ( [class.cdtor]/1 ) y ya se obtuvo el almacenamiento para y ( [basic.life]/7 ), esa referencia puede estar vinculada a y .

Usar esa referencia dentro de la declaración compuesta del constructor (después de que finaliza la inicialización del miembro) también está bien. Esto se debe a que y se considera inicializado, y x refiere ahora a un objeto cuya vida útil ha comenzado.

1 - Hay una advertencia para los abogados de lenguaje. Técnicamente, una referencia debe estar vinculada a un objeto válido ( [dcl.ref]/5 ), es decir, uno cuya vida útil ha comenzado. Sin embargo, al igual que los detalles del Core Language 363 , ¡se espera que funcione! La redacción problemática y una posible resolución se analizan en el número 453 de Core Language (cortesía de @TC en un comentario eliminado). Hay un error en el estándar, pero su código está diseñado para estar bien formado y las implementaciones generalmente lo conocen.