Historia de la cuestión:
En el C++ clásico, los miembros de la clase se inicializaban solo en la lista de inicialización del constructor. Con C++11, se introdujo la posibilidad de especificar valores predeterminados directamente en la declaración dentro de la clase (inicializadores de miembros) para mejorar la legibilidad y la seguridad del código.
Problema:
Existen varias formas de asignar un valor a un miembro de la clase: directamente en la declaración (in-class), a través de la lista de inicialización del constructor y ya en el cuerpo del constructor. Diferentes métodos afectan el rendimiento y la semántica; la comprensión incorrecta lleva a copias innecesarias o destructores predeterminados, errores con constantes y referencias.
Solución:
class MyClass { int x = 42; };
class MyClass { const int y; MyClass(int val) : y(val) {} // de lo contrario — error de compilación };
class MyClass { std::string s; MyClass() { s = "hello"; } // Primero default, luego asignación };
Características clave:
¿Cuál será el orden de inicialización de los miembros: en el orden en que están declarados en la clase o en el orden en la lista de inicialización?
El orden de inicialización siempre es el que se declara en la clase, no en el orden de la lista de inicialización. Alterar el orden es peligroso para los miembros dependientes.
class A { int x = 1; int y = 2; A() : y(10), x(20) {} }; // x se inicializa antes que y, a pesar del orden en la lista
¿Se puede inicializar un miembro constante dentro del cuerpo del constructor si no se ha inicializado en la lista?
No. Las constantes se inicializan solo en la lista de inicialización. La asignación en el cuerpo del constructor es un error de compilación.
¿Qué sucederá si se establece un valor predeterminado para un miembro directamente en la clase a través de un inicializador en la declaración y se anula en la lista de inicialización del constructor?
Se utilizará el valor de la lista de inicialización del constructor. El valor predeterminado se utiliza solo si la lista no indica nada.
class C { int x = 10; C() : x(20) {} // x será igual a 20 };
La clase trabaja con un archivo. El archivo se declara como std::ofstream e inicializa en el cuerpo del constructor. Peligro: con un constructor predeterminado, se podría crear un std::ofstream no válido, lo que provoca errores al trabajar con el archivo.
Ventajas:
Desventajas:
El archivo se inicializa en la lista de inicialización, bloqueando el uso incorrecto del archivo con un estado no válido, mientras que los miembros con datos predeterminados utilizan inicializadores en la declaración.
Ventajas:
Desventajas: