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.