31 votes

Qu'est-ce qu'une liste jointe entre accolades s'il ne s'agit pas d'une liste d'initialisation?

J'ai posé une question ici: la durée de Vie de l'Extension d'un initializer_list retour impliquant la non-fonctionnelle code:

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

Je croyais que le lambda est d'essayer de renvoyer un intializer_list (c'est mal, ne le faites pas.) Mais j'ai reçu un commentaire:

Ce n'est pas un initializer_list, c'est une liste d'initialiseur. De deux choses différentes.

J'ai juste pensé que tout moment vous n'avez bouclé et contreventées liste de la création de l' intializer_list. Si ce n'est pas ce qui se passe, ce qui est une liste dans bouclés-accolades?

29voto

NathanOliver Points 10062

C'est un arc-boutée-init-liste. Un arc-boutée-init-liste existait avant std::initializer_list et est utilisé pour initialiser les agrégats.

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

Le ci-dessus a utilisé un arc-boutée-init-liste d'initialiser le tableau, pas de std::initializer_list est créé. D'autre part, si vous ne

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

foo n'est pas un ensemble, afin de l' arc-boutée-init-liste est utilisée pour créer un std::initializer_list qui est en tournée à passer au constructeur de foo qui accepte un std::initializer_list.

Une chose à noter sur un arc-boutée-init-liste est qui n'a pas de type donc, des règles spéciales ont été développées pour une utilisation avec lui et auto. Il a le comportement suivant (depuis l'adoption de 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

Et vous pouvez obtenir plus d'informations sur l'histoire de ce problème et pourquoi il a été changé à: Pourquoi est-ce que auto x{3} déduire une initializer_list?

12voto

TartanLlama Points 1461

Il y a trois personnes distinctes, mais liées à des concepts ici:

  1. arc-boutée-init-liste: La règle grammaticale associée avec curly-brace-joint les listes dans certains contextes.

  2. La liste des initialiseurs: Le nom de l' arc-boutée-init-liste d'initialiseur utilisé dans la liste d'initialisation.

  3. std::initializer_list: Une classe d'emballage d'un tableau temporaire qui est créé dans certains contextes impliquant moisa-init-listes.

Quelques exemples:

//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 };

Vous voudrez peut-être lire N3922, qui a changé de certaines des règles impliquant auto et std::initializer_list.

7voto

R Sahu Points 24027

J'ai juste pensé que tout moment vous n'avez bouclé et contreventées liste de la création de l' intializer_list.

Ce n'est pas correct.

Si ce n'est pas ce qui se passe, ce qui est une liste dans bouclés-accolades?

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

L' {10, 20} partie n'est pas un initializer_list. C'est juste une forme syntaxique d'utiliser une liste d'objets pour créer un autre objet.

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

Encore une fois, c'est une forme syntaxique de créer un tableau.

Le nom de la forme syntaxique est - braced-init-list.

1voto

Zhen Points 1369

Vous avez deux choses différentes quand utiliser {}

  1. Un Type std::initializer_list<T> où les valeurs peuvent être implicitement converti en T
  2. Un type qui peut être initialisé avec les valeurs de la liste.

Le premier type de forces homogène liste et le second type n'en ont pas. Dans l'exemple suivant:

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

Les fonctions f1 et f2 utiliser le premier type f3 utiliser le deuxième type. Il faut savoir que si il y a ambiguïté, le std::initializer_list est préférée. 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X