¿Los miembros de una estructura C ++ se inicializan a 0 de forma predeterminada?


Respuestas:


264

No son nulos si no inicializa la estructura.

Snapshot s; // receives no initialization
Snapshot s = {}; // value initializes all members

El segundo hará que todos los miembros sean cero, el primero los deja en valores no especificados. Tenga en cuenta que es recursivo:

struct Parent { Snapshot s; };
Parent p; // receives no initialization
Parent p = {}; // value initializes all members

El segundo hará p.s.{x,y}cero. No puede usar estas listas de inicializadores agregados si tiene constructores en su estructura. Si ese es el caso, deberá agregar la inicialización adecuada a esos constructores

struct Snapshot {
    int x;
    double y;
    Snapshot():x(0),y(0) { }
    // other ctors / functions...
};

Inicializará tanto x como y a 0. Tenga en cuenta que puede usar x(), y()para inicializar sin tener en cuenta su tipo: esa es la inicialización del valor, y generalmente produce un valor inicial adecuado (0 para int, 0.0 para doble, llamando al constructor predeterminado para el usuario definido tipos que tienen constructores declarados por el usuario, ...). Esto es importante especialmente si su estructura es una plantilla.


1
Esto produce muchas advertencias en mi compilador.
River-Claire Williamson

1
Roger: Intente usar la estructura con nombre en el inicializador, eso es lo que hago y no recibo ninguna advertencia en VC 2012: Snapshot s = Snapshot ();
Kit10

@Johannes Schaub - litb ¿Funcionará Snapshot s = {};para los miembros que no son POD (por ponerlos a cero)?
ontherocks

2
C ++ 11 ahora le permite inicializarlos en la definición de la estructura o clase, de este modo: struct Snapshot {double x {0}; // con llaves int y = 0; // o simplemente el estilo de la vieja escuela 'por asignación' que también es realmente inicialización};
ikku100

1
Es "Instantánea s = {};" parte de la norma?
Stefan

41

No, no son 0 por defecto. La forma más sencilla de garantizar que todos los valores o predeterminados a 0 es definir un constructor

Snapshot() : x(0), y(0) {
}

Esto asegura que todos los usos de Snapshot tendrán valores inicializados.


24
La desventaja es que la estructura ya no es un tipo POD, porque tiene un constructor. Eso interrumpirá algunas operaciones, como escribirlo en un archivo temporal.
finnw 01 de

16
@finnw: C ++ 11 corrige esto, aunque la estructura no es POD, es "diseño estándar".
Ben Voigt

20

En general, no. Sin embargo, una estructura declarada como alcance de archivo o estática en una función / se inicializará a 0 (al igual que todas las demás variables de esos ámbitos):

int x; // 0
int y = 42; // 42
struct { int a, b; } foo; // 0, 0

void foo() {
  struct { int a, b; } bar; // undefined
  static struct { int c, d; } quux; // 0, 0
}

1
Eso realmente no es una suposición segura. no debe confiar en el valor de nada que no haya inicializado
Hasturkun

24
Los objetos de duración de almacenamiento estático siempre se inicializan a cero; consulte stackoverflow.com/questions/60653/… para obtener una cita del estándar. Si este es un buen estilo es otra cuestión.
bdonlan 01 de

12

Con POD también puedes escribir

Snapshot s = {};

No debe usar memset en C ++, memset tiene el inconveniente de que si hay un no POD en la estructura, lo destruirá.

o así:

struct init
{
  template <typename T>
  operator T * ()
  {
    return new T();
  }
};

Snapshot* s = init();

@LightnessRacesinOrbit oh wat?
Ben Sinclair

@Andy Most Vexing Parse convierte cosas que se parecen a las herramientas normales ( SomeType foo();es la típica, aunque puede suceder con otras) en definiciones de funciones (en ese caso, una función fooque regresa SomeType). Perdón por el necro, pero si alguien más se encuentra con esto, pensé que respondería.
Financia la demanda de Mónica el

8

En C ++, use constructores sin argumentos. En C no puede tener constructores, así que use uno memseto la solución interesante: inicializadores designados:

struct Snapshot s = { .x = 0.0, .y = 0.0 };

Creo que esto es C, no C ++. No se compilará en algunos compiladores de C ++. Experimenté la falla de compilación bajo Cygwin o MinGW.
jww

3

Creo que la respuesta correcta es que sus valores no están definidos. A menudo, se inicializan a 0 cuando se ejecutan versiones de depuración del código. Este no suele ser el caso cuando se ejecutan versiones de lanzamiento.


2
En realidad, las versiones de depuración ya tienen 0en esos lugares en la memoria. ¡Esto no es lo mismo que la inicialización!
ligereza corre en órbita el

3

Dado que este es un POD (esencialmente una estructura C), hay poco daño en inicializarlo de la manera C:

Snapshot s;
memset(&s, 0, sizeof (s));

o de manera similar

Snapshot *sp = new Snapshot;
memset(sp, 0, sizeof (*sp));

Sin embargo, no iría tan lejos como para usarlo calloc()en un programa C ++.


3
Lo mismo vale para el doble; all-bits-zero no es necesariamente 0.0. Sin embargo, puede verificar si tiene dobles IEEE754, en cuyo caso debe funcionar.
MSalters

1

Mueva los miembros del pod a una clase base para acortar su lista de inicializadores:

struct foo_pod
{
    int x;
    int y;
    int z;
};

struct foo : foo_pod
{
    std::string name;
    foo(std::string name)
        : foo_pod()
        , name(name)
    {
    }
};

int main()
{
    foo f("bar");
    printf("%d %d %d %s\n", f.x, f.y, f.z, f.name.c_str());
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.