2009-07-01 13 views

risposta

217

Non sono nulli se non si inizializza la struttura.

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

La seconda farà tutti i membri nullo, il primo li lascia a valori non specificati. Si noti che è ricorsivo:

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

Il secondo farà p.s.{x,y} zero. Non puoi usare questi elenchi di inizializzatori aggregati se hai costruttori nella tua struct. Se questo è il caso, si dovrà aggiungere una corretta inizializzazione del a quei costruttori

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

inizializza xey a 0. Si noti che è possibile utilizzare x(), y() per inizializzare loro senza tener conto del loro tipo: Che è poi l'inizializzazione valore e di solito restituisce un valore iniziale appropriato (0 per int, 0.0 per double, chiamando il costruttore predefinito per i tipi definiti dall'utente che hanno costruttori dichiarati dall'utente, ...). Questo è importante specialmente se la tua struttura è un modello.

+1

Questo produce molti avvisi nel mio compilatore. –

+1

Roger: tenta di utilizzare la struttura denominata nell'inizializzatore, questo è quello che faccio e non ricevo alcun avviso in VC 2012: Snapshot s = Snapshot(); – Kit10

+0

@Johannes Schaub - L'istantanea Willb 's = {};' funziona per i membri non POD (per azzerarli)? – ontherocks

36

No, non sono 0 di default. Il modo più semplice per garantire che tutti i valori o stabilizzato a 0 è quello di definire un costruttore

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

Ciò garantisce che tutti gli usi di istantanee avranno valori inizializzati.

+24

Lo svantaggio è che la struttura non è più un tipo POD, perché ha un costruttore. Ciò interromperà alcune operazioni come la scrittura in un file temporaneo. – finnw

+15

@finnw: C++ 11 lo risolve, sebbene la struttura non sia POD, è "layout standard". –

3

Credo che la risposta corretta sia che i loro valori non sono definiti. Spesso, vengono inizializzati su 0 quando si eseguono versioni di debug del codice. Questo di solito non è il caso quando si eseguono versioni di rilascio.

+2

In realtà, le versioni di debug hanno già "0" in quei posti in memoria. Questo non è lo stesso dell'inizializzazione! –

16

In generale, n. Tuttavia, una struttura dichiarata nel formato-scope o statico in una funzione/sarà/inizializzato a 0 (come tutte le altre variabili di tali ambiti):

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

Questa non è un'ipotesi sicura. non dovresti fare affidamento sul valore di qualcosa che non hai inizializzato – Hasturkun

+17

Gli oggetti di durata di archiviazione statici sono sempre inizializzati a zero - vedi http://stackoverflow.com/questions/60653/is-global-memory-initialized-in-c/ 60707 # 60707 per una citazione dallo standard. Se questo è un buon stile è un'altra questione. – bdonlan

4

Poiché questo è un POD (essenzialmente un C struct) c'è poco danno in inizializzazione nel modo C:

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

né parimenti

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

non vorrei andare fino al punto di usare calloc() in un programma C++ però.

+5

Non è portatile. Il puntatore 0 può avere un valore diverso da 0. –

+1

@Sergey, sì ma questa struttura non contiene puntatori. – finnw

+3

Stesse prese per il doppio; all-bit-zero non è necessariamente 0.0. Tuttavia, è possibile verificare se si dispone di doppio IEEE754, nel qual caso deve funzionare. – MSalters

7

In C++, utilizzare costruttori senza argomento.In C non si può avere costruttori, in modo da utilizzare sia memset o - la soluzione interessante - inizializzatori designati:

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

Credo che questo sia C, non C++. Non riuscirà a compilare sotto alcuni compilatori C++. Ho avuto l'errore di compilazione sotto Cygwin o MinGW. – jww

11

Con il POD è possibile anche scrivere

Snapshot s = {}; 

Non si deve usare memset in C++ , memset ha lo svantaggio che se c'è un non-POD nella struttura lo distruggerà.

o come questo:

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

Snapshot* s = init(); 
+0

[Attenzione per Mr. Most Vexing Parse] (http://codepad.org/utBvhcQ5) –

+0

@LightnessRacesinOrbit oh wat? – Andy

+0

@Andy Most Vexing Parse trasforma cose che assomigliano a normali ctor - 'SomeType foo();' è il tipico, anche se può accadere con gli altri - in definizioni di funzioni (in questo caso, una funzione 'foo' che ritorna 'SomeType'). Scusa per il necro, ma se qualcun altro si imbatte in questo, ho pensato di rispondere. –

1

membri Spostare Pod to una classe base per accorciare la lista di inizializzazione:

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()); 
} 
Problemi correlati