2010-04-10 2 views
22

Sono consapevole che non è possibile utilizzare un elenco di inizializzazione per un array. Tuttavia, ho sentito di modi in cui è possibile impostare un array di puntatori su NULL in un modo simile a un elenco di inizializzatori.C++ Come si imposta un array di puntatori a null in un elenco di inizializzatori come in questo modo?

Non sono sicuro di come sia fatto. Ho sentito che un puntatore è impostato su NULL per impostazione predefinita, anche se non so se questo è garantito/nello standard C++. Inoltre, non sono sicuro che l'inizializzazione attraverso il nuovo operatore rispetto alla normale allocazione possa fare la differenza.

Modifica: Intendo farlo in un file di intestazione/elenco di inizializzazione costruttore. Non voglio metterlo nel costruttore, e non voglio usare un vettore.

risposta

27

Al fine di impostare un array di puntatori ai valori nulli nella lista di inizializzazione del costruttore, è possibile utilizzare il () inizializzatore

struct S { 
    int *a[100]; 

    S() : a() { 
    // `a` contains null pointers 
    } 
}; 

Purtroppo, nella versione attuale del linguaggio l'inizializzatore () è l'unico inizializzatore che si può essere utilizzato con un membro dell'array nell'elenco di inizializzazione del costruttore. Ma a quanto pare questo è ciò di cui hai bisogno nel tuo caso.

Il () ha lo stesso effetto sugli array allocato con new[]

int **a = new int*[100](); 
// `a[i]` contain null pointers 

In altri contesti è possibile utilizzare il {} inizializzatore di aggregazione per ottenere lo stesso effetto

int *a[100] = {}; 
// `a` contains null pointers 

Nota che assolutamente non c'è bisogno per spremere uno 0 o uno NULL tra lo {}. La coppia vuota di {} andrà bene.

+0

Sì! Questo è esattamente quello che volevo, grazie :) – user233320

+5

+1 - Proprio come una parte, C richiede che ci sia almeno un valore tra le parentesi di inizializzazione. C++ aggiunto L'inizializzatore di parentesi graffe ('{}') specificamente perché non c'è ragione per cui il valore predefinito di un oggetto debba essere qualcosa simile a '0', e il codice che richiede l'inizializzazione di un oggetto potrebbe non avere idea di quale impostazione predefinita ragionevole possa essere (in particolare nei modelli). –

+1

Ho pensato che 'int * a = new int [100]();' crea un puntatore a un array di numeri interi che ha un significato inizializzato a zero 'a [i]' dovrebbe contenere 0 ed essere un puntatore dereferenziato al (i + 1) il numero intero di quell'array piuttosto che un puntatore nullo. –

3

Normalmente una matrice non viene inizializzato per default, ma se si inizializza uno o più elementi esplicitamente poi elementi rimanenti verrà inizializzata automaticamente a 0. Da 0 e NULL equivalgono pertanto è possibile inizializzare un array di puntatori a NULL in questo modo:

float * foo[42] = { NULL }; // init array of pointers to NULL 
+1

Attenzione che "int foo1 [42] = {1};" solo inits il primo a 1 e il rimanente a 0, poiché di default C++ si posiziona su 0 elementi di array su 0! Nel tuo esempio, stai impostando solo il primo elemento su 0 e il rimanente è impostato su 0. – amfcosta

+0

@amfcosta: non sono sicuro del motivo per cui pensi che la risposta non sia chiara, o perché meriti un down-vote? L'OP chiedeva di inizializzare array di puntatori a 'NULL'. –

+0

per favore vedi il mio commento. È perché int foo1 [42] = {0}; è fuorviante. – amfcosta

0
void* p[10] = { 0 }; 
+0

Si noti che questo è solo l'inizializzazione esplicita del primo elemento a 0, i rimanenti sono inizializzati a zero per impostazione predefinita da C++. Ad esempio, "int foo1 [42] = {1};" solo inits il primo a 1 e il rimanente a 0, poiché di default C++ si posiziona su 0 elementi di array su 0! – amfcosta

+0

Ancora più importante, il compilatore inizializza le voci rimanenti su all-bit-zero, che non garantisce di essere uguale alla rappresentazione di un puntatore nullo. – kdopen

+0

@kdopen In realtà le voci _remaining_ sono OK; dà esplicitamente '0' che potrebbe essere un problema - cioè si ottiene l'inizializzazione 0 se non si specifica esplicitamente 0.: S _" L'inizializzazione zero viene eseguita [...] per i membri di tipi di classi inizializzate dal valore che hanno nessun costruttore, inclusa l'inizializzazione del valore di elementi di aggregati per i quali non sono forniti inizializzatori. [...] Un puntatore inizializzato a zero è il valore di puntatore nullo del suo tipo, anche se il valore del puntatore nullo non è zero integrale. " _ http://en.cppreference.com/w/cpp/language/zero_initialization Da C++ 11, usare '{}'. –

2

io non sono sicuro di come questo viene fatto. Ho sentito che un puntatore è impostato su NULL per impostazione predefinita, anche se non so se questo è garantito/nello standard C++.
Non è garantito dallo standard C++. I tipi incorporati (come i puntatori) sono pieni di rifiuti, a meno che non sia impostato diversamente.

Non sono sicuro se anche l'inizializzazione tramite il nuovo operatore rispetto alla normale allocazione possa fare la differenza.
Cosa intendi per "allocazione normale"? Se si sta parlando di una variabile automatica, allora si può fare questo:

MyType * pointers[2] = {}

ei puntatori dovrebbe essere inizializzato a NULL.

+1

I puntatori non sono garantiti per essere inizializzati su NULL, proprio come gli ints non sono inizializzati su 0, in molti contesti. Nota che il tuo esempio è equivalente a '{NULL, 0}' e '{}' (preferendo quest'ultimo), piuttosto che specificare un valore per tutti gli elementi dell'array. –

+0

@RogerPate So che questa risposta è scaduta da un po 'di tempo ma l'ho risolta ora. :) –

7

È possibile passare da matrice per std::vector e utilizzare

std::vector<T*> v(SIZE); 

I valori vengono inizializzati NULL s automaticamente. Questo è il modo preferito in C++.


Aggiornamento: Poiché C++ 11, v'è un altro modo: usando

std::array<T*, SIZE> array = {}; 

Questo comporta più come una versione corretta di matrice stile C (in particolare, evita allocazioni dinamiche), trasporta le sue dimensioni intorno e non decadono in un puntatore. La dimensione, tuttavia, deve essere nota al momento della compilazione.

+1

A meno che l'OP non desideri una matrice di dimensioni dinamiche. –

+0

@Billy: Beh, l'OP potrebbe semplicemente ignorare la possibilità di dimensionamento dinamico. C++ - gli array di stile sono generalmente una buona cosa. – Vlad

+3

Se la dimensione è nota al momento della compilazione, gli array incorporati sono migliori. È meglio evitare l'allocazione dinamica quando possibile. 'vettori' dovrebbero essere usati ogni volta che la costante di dimensione non è nota al momento della compilazione. –

-1

Se si dispone di un array membro, non è possibile inizializzarlo, a meno che non sia un membro statico. Se l'array non è un membro statico, dovrai riempirlo all'interno del corpo del costruttore.

Detto questo, è molto meglio usare std::vector. A parte per motivi tecnici come l'indisponibilità di un STL standard per la tua piattaforma, o le prestazioni leggermente inferiori a std::vector è meglio di un array con qualsiasi criterio. Se il problema è il rendimento, assicurati di profilare e sapere per numero che si tratta di un problema.