c++ - programacion - ¿Por qué un POD en una estructura cero inicializado por un constructor implícito al crear un objeto en el montón o un objeto temporal en la pila?
metodos en c++ (2)
Es el comportamiento esperado. Hay dos conceptos, "inicialización por defecto" y "inicialización de valor". Si no menciona ningún inicializador, el objeto está "inicializado por defecto", mientras que si lo menciona, incluso como () para el constructor predeterminado, el objeto está "valor inicializado". Cuando se define el constructor, ambos casos llaman al constructor predeterminado. Pero para los tipos incorporados, la "inicialización del valor" pone a cero la memoria, mientras que la "inicialización predeterminada" no lo hace.
Así que cuando se inicializa:
Type x;
llamará al constructor predeterminado si se proporciona uno, pero los tipos primitivos no estarán inicializados. Sin embargo, cuando mencionas un inicializador, por ejemplo
Type x = {}; // only works for struct/class without constructor
Type x = Type();
Type x{}; // C++11 only
un tipo primitivo (o miembros primitivos de una estructura) será inicializado con VALOR.
Del mismo modo para:
struct X { int x; X(); };
si define el constructor
X::X() {}
el miembro x no estará inicializado, pero si define el constructor
X::X() : x() {}
Será VALOR-inicializado. Eso se aplica a lo new
también, así que
new int;
debería darle memoria no inicializada, pero
new int();
debe darle memoria inicializada a cero. Desafortunadamente la sintaxis:
Type x();
No está permitido debido a la ambigüedad gramatical y
Type x = Type();
está obligado a llamar al constructor por defecto seguido por el constructor de copia si ambos están especificados y no en línea.
C ++ 11 introduce nueva sintaxis,
Type x{};
Que es utilizable para ambos casos. Si aún está atascado con el estándar anterior, es por eso que hay Boost.ValueInitialized, por lo que puede inicializar correctamente la instancia del argumento de la plantilla.
Se puede encontrar una discusión más detallada, por ejemplo, en la documentación de Boost.ValueInitialized .
El estándar y el libro de C ++ dicen que el constructor predeterminado generado por los miembros de tipo de clase es llamado por el constructor predeterminado implícito generado, pero los tipos integrados no se inicializan. Sin embargo, en este programa de prueba obtengo resultados inesperados al asignar un objeto en el montón o al usar un objeto temporal:
#include<iostream>
struct Container
{
int n;
};
int main()
{
Container c;
std::cout << "[STACK] Num: " << c.n << std::endl;
Container *pc = new Container();
std::cout << "[HEAP] Num: " << pc->n << std::endl;
delete pc;
Container tc = Container();
std::cout << "[TEMP] Num: " << tc.n << std::endl;
}
Obtengo esta salida:
[STACK] Num: -1079504552
[HEAP] Num: 0
[TEMP] Num: 0
¿Es este un comportamiento específico del compilador? Realmente no tengo la intención de confiar en esto, pero tengo curiosidad por saber por qué sucede esto, especialmente en el tercer caso.
La respuesta corta es: los paréntesis vacíos realizan la inicialización del valor .
Cuando dices Container *pc = new Container;
En cambio, observarás diferentes comportamientos.