I membri di una struttura C ++ sono inizializzati su 0 per impostazione predefinita?


Risposte:


264

Non sono nulli se non si inizializza la struttura.

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

Il secondo renderà zero tutti i membri, il primo li lascerà 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 struttura. In tal caso, dovrai aggiungere una corretta inizializzazione a quei costruttori

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

Inizializzerà sia x che y su 0. Si noti che è possibile utilizzare x(), y()per inizializzarli ignorando il loro tipo: Questo è quindi l'inizializzazione del valore e di solito produce un valore iniziale corretto (0 per int, 0,0 per doppio, chiamando il costruttore predefinito per l'utente definito tipi con costruttori dichiarati dall'utente, ...). Questo è importante soprattutto se la tua struttura è un modello.


1
Questo produce molti avvisi nel mio compilatore.
River-Claire Williamson,

1
Roger: prova a usare la struttura con nome nell'inizializzatore, ecco cosa faccio e non ricevo alcun avviso in VC 2012: Snapshot s = Snapshot ();
Kit10

@Johannes Schaub - litb Funzionerà Snapshot s = {};per i membri non POD (per azzerarli)?
ontherocks,

2
C ++ 11 ora ti consente di inizializzarli nella definizione della struttura o della classe, in questo modo: struct Snapshot {double x {0}; // con parentesi graffe int y = 0; // o solo lo stile di vecchia scuola "per incarico", che in realtà è anche inizializzazione};
ikku100,

1
"Snapshot s = {};" parte dello standard?
Stefan,

41

No, non sono 0 per impostazione predefinita. Il modo più semplice per garantire che tutti i valori o il valore predefinito siano 0 è definire un costruttore

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

Ciò garantisce che tutti gli usi di Snapshot abbiano valori inizializzati.


24
Il rovescio della medaglia è che la struttura non è più un tipo POD, perché ha un costruttore. Ciò interromperà alcune operazioni come scriverlo in un file temporaneo.
Finnw,

16
@finnw: C ++ 11 risolve questo problema, sebbene la struttura non sia POD, è "layout standard".
Ben Voigt,

20

In generale, no. Tuttavia, una struttura dichiarata come ambito di file o statica in una funzione / verrà / verrà inizializzata su 0 (proprio 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
Questo non è davvero un presupposto sicuro. non dovresti fare affidamento sul valore di tutto ciò che non hai inizializzato
Hasturkun,

24
Gli oggetti con durata di archiviazione statica vengono sempre inizializzati su zero - consultare stackoverflow.com/questions/60653/… per una citazione dallo standard. Se questo è un buon stile è un'altra questione.
bdonlan,

12

Con POD puoi anche scrivere

Snapshot s = {};

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

o in questo modo:

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

Snapshot* s = init();

@LightnessRacesinOrbit oh wat?
Ben Sinclair,

@Andy Most Vexing Parse trasforma le cose che assomigliano a normali maledizioni - SomeType foo();è quella tipica, sebbene possa accadere con gli altri - in definizioni di funzioni (in quel caso, una funzione fooche ritorna SomeType). Ci scusiamo per il necro, ma se qualcun altro si imbatte in questo, ho pensato che avrei risposto.
Fondi Monica's Lawsuit,

8

In C ++, utilizzare i costruttori senza argomento. In C non puoi avere costruttori, quindi usa uno memseto - la soluzione interessante - inizializzatori designati:

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

Credo che questo sia C, non C ++. Non verrà compilato con alcuni compilatori C ++. Ho riscontrato l'errore di compilazione sotto Cygwin o MinGW.
jww

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 sono già presenti 0in quei posti in memoria. Questo non è lo stesso dell'inizializzazione!
Razze di leggerezza in orbita il

3

Dato che si tratta di un POD (essenzialmente una struttura in C), l'inizializzazione in modo C presenta pochi danni:

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

o similmente

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

Non andrei così lontano da usare calloc()in un programma C ++.


3
Lo stesso vale per il doppio; all-bit-zero non è necessariamente 0,0. Tuttavia, puoi verificare se hai IEEE754 doppie, nel qual caso deve funzionare.
MSalters,

1

Sposta i membri del pod in una classe base per abbreviare l'elenco di inizializzatori:

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());
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.