30

я задал вопрос здесь: Lifetime Extension of a initializer_list return с участием нефункционального кода:Что такое фигурная фигурная скобка, если не intializer_list?

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

Я полагал, что лямбда пыталась вернуть intializer_list (это плохо, не делайте этого.) Но я получил comment:

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

Я просто подумал, что в любое время вы сделали список кудрявого-приготовился вы создавали intializer_list. Если это не то, что происходит, что такое список в фигурных скобках?

+0

Это просто: ошибка: возвращает список инициализаторов. –

+1

@ DieterLücking Должно быть, ваши ошибки поднялись выше, чем у меня. Я даже не получил предупреждение в первый раз, когда я попробовал это, хотя, как указано в связанном вопросе, это * не * хороший код. –

+0

@JonathanMee Ниже SO вопрос имеет также некоторые полезные ответы: http://stackoverflow.com/questions/29200036/is-providing-a-private-constructor-for-initializer-list-conforming – Arunmu

ответ

10

Есть три различных, но связанных понятий здесь:

  1. приготовился-INIT-лист: Грамматический правило, связанные с фигурными скобками вложенных списков в определенных контекстах.

  2. Initializer список: Имя для приготовился-INIT-лист инициализатора используется в списке инициализации.

  3. std::initializer_list: класс, который включает временный массив, который создается в некоторых контекстах с участием . Braced-init-list s.

Некоторые примеры:

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

Вы можете прочитать N3922, который изменил некоторые правила, связанных с auto и std::initializer_list.

28

Это скошенный начальный список. A braced-init-list существует до std::initializer_list и используется для initialize aggregates.

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

выше использовали рамно-Init-список для инициализации массива, не std::initializer_list не создается. С другой стороны, когда вы делаете

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

foo не агрегат так приготовился-INIT-лист используется для создания std::initializer_list, который в свернули передается конструктору foo, который принимает std::initializer_list.

Замечание относительно braced-init-list - это не имеет типа, поэтому для его использования были разработаны специальные правила и auto. Она имеет следующее поведение (со времени принятия 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 

И вы можете получить более подробную информацию об истории этого поведения, и почему оно было изменено на: Why does auto x{3} deduce an initializer_list?

+0

Итак, если да, 'auto foo = {1, 2, 3, 4, 5}' какой тип 'foo'? Гарантировано ли это 'intializer_list'? –

+1

@JonathanMee Я думаю, что обновление должно теперь охватывать это. – NathanOliver

+0

Хотелось бы, чтобы у нас было лучшее имя, чем нетерминал ... –

7

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

Это не правильно.

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

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

{10, 20} часть не является initializer_list. Это просто синтаксическая форма, чтобы использовать список объектов для создания другого объекта.

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

Опять же, это синтаксическая форма для создания массива.

Название синтаксической формы: braced-init-list.

+0

Такой же вопрос, который я задал, @NathanOliver: «Если я это делаю,' auto foo = {1, 2, 3, 4, 5} 'какой тип' foo'? Гарантируется ли это 'intializer_list'? " –

+1

Это будет 'std :: initializer_list '. –

1

У вас есть две разные вещи, когда использование {}

  1. A Тип std::initializer_list<T> где значения могут быть неявно преобразованы в T
  2. типа, который может быть инициализирован со значениями списка.

Первый тип заставляет однородный список, а второй тип - нет. В следующем примере:

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 

Функции f1 и f2 используют первый тип и f3 используют второй тип. Вы должны знать, что если есть двусмысленность, предпочитается std :: initializer_list. Например:

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 

 Смежные вопросы

  • Нет связанных вопросов^_^