¿Qué significan las siguientes frases en C++: inicialización cero, predeterminada y de valor?

Resuelto Bill asked hace 15 años • 2 respuestas

¿Qué significan las siguientes frases en C++?

  • inicialización cero,

  • inicialización predeterminada, y

  • inicialización de valor

¿Qué debería saber un desarrollador de C++ sobre ellos?

Bill avatar Oct 23 '09 20:10 Bill
Aceptado

C++03 Estándar 8.5/5:

Inicializar a cero un objeto de tipo T significa:
— si T es un tipo escalar (3.9), el objeto se establece en el valor de 0 (cero) convertido a T;
— si T es un tipo de clase no sindical, cada miembro de datos no estático y cada subobjeto de clase base está inicializado en cero;
— si T es un tipo de unión, el primer miembro de datos nombrado del objeto tiene inicialización cero;
— si T es un tipo de matriz, cada elemento se inicializa con cero;
— si T es un tipo de referencia, no se realiza ninguna inicialización.

Inicializar por defecto un objeto de tipo T significa:
— si T es un tipo de clase que no es POD (cláusula 9), se llama al constructor predeterminado para T (y la inicialización está mal formada si T no tiene un constructor predeterminado accesible);
— si T es un tipo de matriz, cada elemento se inicializa por defecto;
— de lo contrario, el objeto se inicializa a cero.

Inicializar el valor de un objeto de tipo T significa:
— si T es un tipo de clase (cláusula 9) con un constructor declarado por el usuario (12.1), entonces se llama al constructor predeterminado para T (y la inicialización está mal formada si T no tiene un constructor predeterminado accesible);
— si T es un tipo de clase no sindical sin un constructor declarado por el usuario, entonces cada miembro de datos no estáticos y componente de clase base de T está inicializado por valor;
— si T es un tipo de matriz, entonces cada elemento se inicializa con su valor;
— de lo contrario, el objeto se inicializa a cero

Un programa que solicita una inicialización predeterminada o una inicialización de valor de una entidad de tipo de referencia está mal formado. Si T es un tipo calificado con cv, la versión no calificada con cv de T se usa para estas definiciones de inicialización cero, inicialización predeterminada e inicialización de valor.

Kirill V. Lyadvinsky avatar Oct 23 '2009 13:10 Kirill V. Lyadvinsky

Una cosa a tener en cuenta es que la 'inicialización de valores' es nueva en el estándar C++ 2003; no existe en el estándar original de 1998 (creo que podría ser la única diferencia que es más que una aclaración). Consulte la respuesta de Kirill V. Lyadvinsky para conocer las definiciones directamente del estándar.

Consulte esta respuesta anterior sobre el comportamiento de operator newpara obtener detalles sobre los diferentes comportamientos de este tipo de inicialización y cuándo se activan (y cuándo difieren de C++98 a C++03):

  • ¿Los paréntesis después del nombre del tipo hacen una diferencia con new?

El punto principal de la respuesta es:

A veces, la memoria devuelta por el nuevo operador se inicializará y, a veces, no, dependiendo de si el tipo que está actualizando es un POD o si es una clase que contiene miembros POD y utiliza un constructor predeterminado generado por el compilador. .

  • En C++ 1998 hay 2 tipos de inicialización: cero y predeterminada
  • En C++ 2003 se agregó un tercer tipo de inicialización, la inicialización de valores.

Por decir lo menos, es bastante complejo y cuando los diferentes métodos entran en acción son sutiles.

Una cosa a tener en cuenta es que MSVC sigue las reglas de C++98, incluso en VS 2008 (VC 9 o cl.exe versión 15.x).

El siguiente fragmento muestra que MSVC y Digital Mars siguen las reglas de C++98, mientras que GCC 3.4.5 y Comeau siguen las reglas de C++03:

#include <cstdio>
#include <cstring>
#include <new>

struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m

int main()
{
    char buf[sizeof(B)];
    std::memset( buf, 0x5a, sizeof( buf));

    // use placement new on the memset'ed buffer to make sure 
    //  if we see a zero result it's due to an explicit 
    //  value initialization
    B* pB = new(buf) B();   //C++98 rules - pB->m is uninitialized
                            //C++03 rules - pB->m is set to 0
    std::printf( "m  is %d\n", pB->m);
    return 0;
}
Michael Burr avatar Oct 23 '2009 13:10 Michael Burr