¿El constructor predeterminado inicializa los tipos incorporados?

¿El constructor predeterminado (creado por el comstackdor) inicializa los tipos incorporados?

El constructor predeterminado de una clase definido implícitamente (por el comstackdor) no inicializa los miembros de los tipos incorporados.

Sin embargo, debe tener en cuenta que, en algunos casos, la inicialización de una instancia de la clase puede realizarse por otros medios. No por constructor predeterminado, ni por constructor en absoluto.

Por ejemplo, existe una creencia incorrecta generalizada de que para la clase C la syntax C() siempre invoca el constructor predeterminado. Sin embargo, en realidad, la syntax C() realiza la llamada inicialización de valor de la instancia de clase. Solo invocará el constructor predeterminado si es declarado por el usuario . (Eso está en C ++ 03. En C ++ 98, solo si la clase no es POD). Si la clase no tiene un constructor declarado por el usuario, entonces el C() no llamará al constructor predeterminado provisto por el comstackdor, sino que realizará un tipo especial de inicialización que no involucra al constructor de C en absoluto. En cambio, va a inicializar el valor directamente a cada miembro de la clase. Para los tipos incorporados, da como resultado una inicialización cero.

Por ejemplo, si su clase no tiene un constructor declarado por el usuario

 class C { int x; }; 

entonces el comstackdor proporcionará implícitamente uno. El constructor provisto por el comstackdor no hará nada, lo que significa que no inicializará C::x

 C c; // Compiler-provided default constructor is used // Here `cx` contains garbage 

Sin embargo, las siguientes inicializaciones inicializarán cero porque usan el inicializador explícito ()

 C c = C(); // Does not use default constructor for `C()` part // Uses value-initialization feature instead assert(cx == 0); C *pc = new C(); // Does not use default constructor for `C()` part // Uses value-initialization feature instead assert(pc->x == 0); 

El comportamiento del inicializador () es diferente en algunos aspectos entre C ++ 98 y C ++ 03, pero no en este caso. Para la clase C anterior, será la misma: () inicializador realiza la inicialización cero de C::x .

Otro ejemplo de inicialización que se realiza sin involucrar constructor es, por supuesto, la inicialización agregada

 C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11. assert(cx == 0); C d{}; // C++11 style aggregate initialization. assert(dx == 0); 

Para todos los propósitos prácticos – no.


Sin embargo, para las implementaciones que son técnicamente compatibles con el estándar de C ++, la respuesta es que depende de si el objeto es POD o no y de cómo se inicializa. De acuerdo con el estándar C ++:

 MyNonPodClass instance1;//built in members will not be initialized MyPodClass instance2;//built in members will be not be initialized MyPodClass* instance3 = new MyPodClass;//built in members will not be initialized MyPodClass* instance3 = new MyPodClass() ;//built in members will be zero initialized 

Sin embargo, en el mundo real, esto no está bien soportado, así que no lo use.


Las partes relevantes de la norma son la sección 8.5.5 y 8.5.7

No estoy muy seguro de lo que quieres decir, pero:

 struct A { int x; }; int a; // a is initialized to 0 A b; // bx is initialized to 0 int main() { int c; // c is not initialized int d = int(); // d is initialized to 0 A e; // ex is not initialized A f = A(); // fx is initialized to 0 } 

En cada caso en que digo “no inicializado”, es posible que el comstackdor le proporcione un valor constante, pero el estándar no lo requiere.

Se lanza una gran cantidad de movimientos manuales, incluido yo, sobre cómo los tipos incorporados “en efecto” tienen un constructor predeterminado. En realidad, la inicialización predeterminada y la inicialización de valores son términos definidos en el estándar, que personalmente debo buscar cada vez. Solo las clases se definen en el estándar para tener un constructor predeterminado implícito.

Según el estándar, no lo hace a menos que inicie explícitamente en la lista de inicializadores

Como han dicho los oradores anteriores, no, no se inicializaron.

En realidad, esto es una fuente de errores realmente extraños, ya que los sistemas operativos modernos tienden a llenar las regiones de memoria recién asignadas con ceros. Si espera eso, podría funcionar la primera vez. Sin embargo, a medida que su aplicación sigue ejecutándose, delete -ing y newing-objects, tarde o temprano terminará en una situación en la que espera ceros pero se encuentra un residuo distinto de cero de un objeto anterior.

Entonces, ¿por qué es esto, entonces, no todos los datos nuevos se asignaron nuevamente? Sí, pero no siempre del sistema operativo. El sistema operativo tiende a trabajar con fragmentos de memoria más grandes (por ejemplo, 4MB a la vez), por lo que todas las pequeñas asignaciones y desasignaciones de una sola palabra-aquí-tres-bytes-allí se manejan en uyserpace, y por lo tanto no se ponen a cero.

PD. Escribí “tender”, es decir, ni siquiera puedes confiar en el éxito la primera vez …

Técnicamente, los inicializa, utilizando su constructor predeterminado, que por cierto no hace más que asignarles la memoria.

Si lo que quería saber es si están configurados para algo sensato como 0 para int s, entonces la respuesta es “no”.

No. El constructor predeterminado asigna memoria y llama al constructor sin argumentos de cualquier padre.