2015-07-07 14 views
8

La seguente è una citazione da Effective C++ moderno (pagina 55):Le parentesi graffe vuote chiamano il costruttore predefinito o il costruttore che prende una lista std :: initializer_list?

"Supponiamo di utilizzare un paio di graffe vuote per costruire un oggetto che supporta costruttore di default e supporta anche std :: initializer_list costruzione Cosa significano le tue parentesi vuote? Ecc. La regola è che ottieni la costruzione predefinita. "

ho provato questo con std :: array:

std::array<int, 10> arr{}; 

e ottenuto l'avvertimento da g ++ (versione 4.8.2):

avvertimento: inizializzatore per il membro mancante 'std: : array < int, 10ul> :: _ M_elems '

quale è l'avviso che si ottiene quando si tenta di costruire uno std::array da un vuoto std::initializer_list (vedere Why can I initialize a regular array from {}, but not a std::array per una discussione di questo avviso).

Quindi, perché la riga di codice precedente non è interpretata come chiamata al costruttore predefinito?

+0

'std :: array' non ha costruttore che prende una' std :: initializer_list', e l'inizializzatore che hai qui non è neanche uno 'std :: initailizer_list'. Si riferisce a un elenco di init rinforzato. Non sono sicuro del motivo per cui ricevi un avviso, poiché l'uso di parentesi graffe dovrebbe valore-inizializzare l'array nidificato. – 0x499602D2

+0

@ 0x499602D2 vedi la mia risposta alla domanda collegata, gcc era aggressivo e le versioni successive di gcc non producono l'avviso. –

+0

Si noti inoltre che hanno cambiato lo standard C++ 11 in modo significativo in un DR. Lo standard attuale dice una cosa, ma i compilatori dovrebbero fare qualcosa di completamente diverso. – o11c

risposta

8

Questo perché std::array è un aggregato e quindi aggregate initialization viene eseguita questa è coperto nella sezione draft C++11 standard8.5.4[dcl.init.list] che dice:

List-inizializzazione di un oggetto o di riferimento di tipo T è definito come segue:

  • Se la lista di inizializzazione non ha elementi e T è un tipo di classe con un costruttore di default, l'oggetto è valore inizializzato.

  • In caso contrario, se T è un aggregato, viene eseguita l'inizializzazione di aggregazione (8.5.1).

    double ad[] = { 1, 2.0 }; // OK 
    int ai[] = { 1, 2.0 }; // error: narrowing 
    
    struct S2 { 
        int m1; 
        double m2, m3; 
    }; 
    
    S2 s21 = { 1, 2, 3.0 }; // OK 
    S2 s22 { 1.0, 2, 3 }; // error: narrowing 
    S2 s23 { }; // OK: default to 0,0,0 
    

e possiamo vedere se non è un aggregato, allora la lista va avanti e dice:

  • In caso contrario, se T è una specializzazione di std :: initializer_list , un oggetto initializer_list è costruito come descritto di seguito e utilizzato per inizializzare l'oggetto in base alle regole per l'inizializzazione di di un oggetto da una classe dello stesso tipo (8.5).
  • Altrimenti, se T è un tipo di classe, vengono considerati i costruttori. I costruttori applicabili sono enumerati e il migliore viene scelto tramite la risoluzione di sovraccarico (13.3, 13.3.1.7). Se una conversione di restringimento (vedere qui sotto) è richiesta per convertire qualsiasi argomento, il programma è mal formato.

Possiamo confermare std::array è un aggregato dalla sezione 23.3.2.1[array.overview]:

Una matrice è un aggregato (8.5.1) che può essere inizializzato con la sintassi

array<T, N> a = { initializer-list }; 

dove inizializzatore-list è un elenco separato da virgole fino a N elementi cui tipi sono convertibili in T.

sezione 8.5.1 si fa riferimento è 8.5.1 Aggregati [dcl.init.aggr] e dice:

Quando un aggregato viene inizializzato da una lista di inizializzazione, come specificato in 8.5.4, gli elementi dell'elenco di inizializzazione sono considerati come inizializzatori per i membri dell'aggregato, nell'applicativo crescente o nell'ordine membro [...]

e torniamo a tutto campo alla sezione 8.5.4 che è dove abbiamo iniziato.

+0

Potresti fornire un link al documento standard che hai citato (se è liberamente accessibile, ovviamente)? – AlwaysLearning

+0

@MeirGoldenberg aggiunto il collegamento nella risposta, è possibile vedere [Dove trovo gli attuali documenti standard C o C++?] (Http://stackoverflow.com/questions/81656/where-do-i-find-the- current-c-or-c-standard-documents) che elenca tutte le bozze disponibili al pubblico. –

Problemi correlati