30

ho fatto una domanda qui: Lifetime Extension of a initializer_list return che coinvolge il codice non funzionale:Che cos'è un elenco racchiuso tra parentesi graffe se non un elenco intializer?

const auto foo = [](const auto& a, const auto& b, const auto& c) { return {a, b, c}; }; 

ho creduto lambda stava cercando di restituire un intializer_list (che è male, non farlo.) Ma ho ottenuto un comment:

It's not an initializer_list , it's an initializer list. Two different things.

ho solo pensato che ogni volta che ha fatto un elenco parentesi graffe si intende creare un intializer_list. Se questo non è ciò che sta accadendo, che cos'è un elenco di parentesi graffe?

+0

È solo: errore: restituire l'elenco di inizializzazione. –

+1

@ DieterLücking Devi avere i tuoi errori alzati più in alto di me. Non ho nemmeno ricevuto un avvertimento la prima volta che ho provato questo, anche se come indicato nella domanda collegata questo non è * buon codice. –

+0

@ JonathanMee Sotto SO domanda ha anche alcune risposte utili per sapere: http://stackoverflow.com/questions/29200036/is-providing-a-private-constructor-for-initializer-list-conforming – Arunmu

risposta

10

ci sono tre distinti, ma concetti relativi qui:

  1. rinforzato-init-list: la regola grammaticale associato con le liste parentesi graffe-chiusi in determinati contesti.

  2. lista di inizializzazione: Il nome per il rinforzato-init-list di inizializzazione utilizzato in lista-inizializzazione.

  3. std::initializer_list: Una classe avvolgendo un array temporaneo che viene creato in alcuni contesti che coinvolgono rinforzato-init-list s.

Alcuni esempi:

//a braced-init-list and initializer list, 
//but doesn't create a std::initializer_list 
int a {4}; 

//a braced-init-list and initializer list, 
//creates a std::initializer_list 
std::vector b {1, 2, 3}; 

//a braced-init-list and initializer list, 
//does not create a std::initializer_list (aggregate initialization) 
int c[] = {1, 2, 3}; 

//d is a std::initializer_list created from an initializer list 
std::initializer_list d {1, 2, 3}; 

//e is std::initializer_list<int> 
auto e = { 4 }; 

//f used to be a std::initializer_list<int>, but is now int after N3922 
auto f { 4 }; 

si potrebbe desiderare di leggere N3922, che ha cambiato alcune delle regole che coinvolgono auto e std::initializer_list.

28

È un controverso-init-list. A controverso-init-list esisteva prima dello std::initializer_list e viene utilizzato per initialize aggregates.

int arr[] = {1,2,3,4,5}; 

Quanto sopra usato un controventata-init-list per inizializzare l'array, non si crea alcun std::initializer_list. D'altra parte, quando si fa

std::vector<int> foo = {1,2,3,4,5}; 

foo non è un aggregato in modo che il rinforzato-init-list viene utilizzato per creare un std::initializer_list che è in svoltò passato al costruttore di foo che accetta un std::initializer_list.

Una cosa da notare su un rinforzato-init-list è che è non ha alcun tipo di regole in modo speciali sono stati sviluppati per l'utilizzo con esso e auto. Essa ha il seguente comportamento (dall'adozione del N3922)

auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int> 
auto x2 = { 1, 2.0 }; // error: cannot deduce element type 
auto x3{ 1, 2 }; // error: not a single element 
auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int> 
auto x5{ 3 }; // decltype(x5) is int 

e si possono ottenere maggiori informazioni sulla storia di questo comportamento e perché è stato modificato in: Why does auto x{3} deduce an initializer_list?

+0

Quindi, se lo faccio, 'auto foo = {1, 2, 3, 4, 5}' qual è il tipo di 'pippo'? È garantito che sia un 'intializer_list'? –

+1

@ JonathanMee Penso che l'aggiornamento dovrebbe coprirlo ora. – NathanOliver

+0

Vorrei avere un nome migliore per questo rispetto al non terminale ... –

7

I just thought that any time you did a curly-braced list you were creating an intializer_list .

Questo non è corretto.

If that's not what's happening, what is a list in curly-braces?

struct Foo {int a; int b;}; 
Foo f = {10, 20}; 

La {10, 20} parte non è un initializer_list. È solo una forma sintattica per usare un elenco di oggetti per creare un altro oggetto.

int a[] = {10, 20, 30}; 

Ancora una volta, è una forma sintattica per creare un array.

Il nome per il modulo sintattico è braced-init-list.

+0

Quindi la stessa domanda che ho chiesto, @NathanOliver: "Se lo faccio,' auto foo = {1, 2, 3, 4, 5} 'qual è il tipo di' foo'? È garantito che sia un 'intializer_list'? " –

+1

Quello sarà un 'std :: initializer_list '. –

1

Hai due cose diverse quando uso {}

  1. A Tipo std::initializer_list<T> dove i valori possono essere convertiti in modo implicito T
  2. Un tipo che può essere inizializzato con i valori della lista.

Il primo tipo forza un elenco omogeneo e il secondo tipo no. Nel prossimo esempio:

struct S{ 
    int a; 
    string b 
}; 

void f1(S s); 
void f2(int i); 
void f3(std::initializer_list<int> l); 

f1({1, "zhen"}); // construct a temporal S 
f2({1});   // construct a temporal int 
f3({1,2,3});  // construct a temporal list of ints 

Le funzioni f1 e f2 utilizzano il primo tipo e f3 utilizzano il secondo tipo. Dovresti sapere che se c'è ambiguità, è preferibile la lista std :: initializer_list. E.g:

void f(S s); 
void f(int i); 
void f(std::initializer_list<int> l); 

f({1, "zhen"}); // calls with struct S 
f({1});   // calls with int list with one element 
f({1,2,3});  // calls with int list with three elements 
Problemi correlati