2009-07-01 13 views

Respuesta

217

No son nulas 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, se le tiene que añadir initalization 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. Obsérvese que se puede utilizar x(), y() inicializarlas haciendo caso omiso de su tipo: Eso es entonces el valor de inicialización , y generalmente produce un valor inicial adecuado (0 para int, 0.0 para double, llamando al constructor predeterminado para tipos definidos por el usuario 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. –

+1

Roger: Trate de usar la estructura nombrada en el inicializador, eso es lo que hago y no recibo ninguna advertencia en VC 2012: instantánea s = instantánea(); – Kit10

+0

@Johannes Schaub - litb Will 'Snapshot s = {};' funciona para los miembros que no pertenecen a POD (para ponerlos a cero)? – ontherocks

36

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

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

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

+24

El inconveniente es que la estructura ya no es un tipo de POD, porque tiene un constructor. Eso interrumpirá algunas operaciones, como escribirlo en un archivo temporal. – finnw

+15

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

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 simplemente ya tienen '0' en esos lugares en la memoria. ¡Esto no es lo mismo que la inicialización! –

16

En general, no. Sin embargo, una estructura declarada como archivo-alcance o estática en una función/será/ser inicializado a 0 (al igual que todas las otras variables de aquellos á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 no es una suposición segura. no debe confiar en el valor de nada que no haya inicializado – Hasturkun

+17

Los objetos de duración de almacenamiento estático siempre se inicializan a cero; consulte http://stackoverflow.com/questions/60653/is-global-memory-initialized-in-c/ 60707 # 60707 para una cita del estándar. Si esto es un buen estilo es otro asunto. – bdonlan

4

Dado que este es un POD (esencialmente un struct C) hay poco daño en la inicialización de la manera C:

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

o similarmente

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

yo no iría tan lejos como para usar calloc() en un programa en C++ sin embargo.

+5

No es portátil. El puntero 0 puede tener un valor distinto de 0. –

+1

@Sergey, sí, pero esta estructura no contiene punteros. – finnw

+3

Lo mismo vale para el doble; todo-bits-cero no es necesariamente 0.0. Sin embargo, puede verificar si tiene duplicados IEEE754, en cuyo caso debe funcionar. – MSalters

7

En C++, utilice constructores sin argumento.En C no se puede tener constructores, a fin de utilizar ya sea memset o - la solución interesante - inicializadores designados:

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

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

11

Con POD también se puede escribir

Snapshot s = {}; 

no debería utilizar memset en C++ , memset tiene el inconveniente de que si hay un no-POD en la estructura lo destruirá.

o como esto:

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

Snapshot* s = init(); 
+0

[Tenga cuidado con Mr. Most Vexing Parse] (http://codepad.org/utBvhcQ5) –

+0

@LightnessRacesinOrbit oh wat? – Andy

+0

@Andy Most Vexing Parse convierte cosas que parecen ctors normales - 'SomeType foo();' es el típico, aunque puede pasar con otros - en definiciones de funciones (en ese caso, una función 'foo' que devuelve 'SomeType'). Perdón por el necro, pero si alguien más tropieza con esto, pensó que respondería. –

1

miembros Mover vaina a una clase base para acortar su lista de inicialización:

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()); 
} 
Cuestiones relacionadas