Что такое закрытый список фигурных скобок, если не список intializer_list?
Я задал здесь вопрос: Lifetime Расширение возврата initializer_list с использованием нефункционального кода:
const auto foo = [](const auto& a, const auto& b, const auto& c) { return {a, b, c}; };
Я полагал, что lambda пыталась вернуть intializer_list
(это плохо, не делайте этого). Но я получил комментарий :
Это не
initializer_list
, это список инициализаторов. Две разные вещи.
- Использование анонимных пространств имен в файлах заголовков
- Как инициализировать частные статические члены в C ++?
- Инициализация авто-свойств C #
- Какова мотивация, заключающаяся в том, что копирование и прямая инициализация ведут себя по-другому?
- Включена ли новая функция инициализации члена C ++ 11 при объявлении, что списки инициализации устарели?
Я просто подумал, что всякий раз, когда вы делаете фигурный скопированный список, вы создаете список intializer_list
. Если это не то, что происходит, что такое список в фигурных скобках?
- статическая инициализация
- C инициализация структуры с использованием меток. Это работает, но как?
- Java: определение терминов инициализация, декларация и присвоение
- C ++ где инициализировать статический const
- Как вызвать метод после инициализации бина?
- Создание объекта в стеке / куче?
- Как я могу использовать массив указателей функций?
- Array vs Array - Инициализация массива с переменным vs действительным числом
Здесь есть три различные, но связанные с ними понятия:
-
braced-init-list : грамматическое правило, связанное с вложенными в фигурные скобки списками в определенных контекстах.
-
Список инициализатора: имя инициализатора списка бит- инициализации, используемого в инициализации списка .
-
std::initializer_list
: class, который обертывает временный массив, который создается в некоторых контекстах, включая список бит-init-list .
Некоторые примеры:
//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 auto e = { 4 }; //f used to be a std::initializer_list , but is now int after N3922 auto f { 4 };
Возможно, вам захочется прочитать N3922 , который изменил некоторые правила, связанные с auto
и std::initializer_list
.
Это бит-init-list . Список привязанных-init-list существовал до std::initializer_list
и используется для инициализации агрегатов .
int arr[] = {1,2,3,4,5};
В приведенном выше примере был использован бит-init-list для инициализации массива, не создается std::initializer_list
. С другой стороны, когда вы это делаете
std::vector foo = {1,2,3,4,5};
foo
не является агрегированным, поэтому бит-init-list используется для создания std::initializer_list
который передается в конструктор foo
который принимает std::initializer_list
.
Замечание о скобках-init-list состоит в том, что у него нет типа, поэтому были разработаны специальные правила для использования с ним и auto
. Он имеет следующее поведение (с момента принятия N3922 )
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list 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 auto x5{ 3 }; // decltype(x5) is int
И вы можете получить дополнительную информацию об истории этого поведения и о том, почему он был изменен: Почему auto x {3} выводит initializer_list?
Я просто подумал, что всякий раз, когда вы делаете фигурный скопированный список, вы создаете список
intializer_list
.
Это неправильно.
Если это не то, что происходит, что такое список в фигурных скобках?
struct Foo {int a; int b;}; Foo f = {10, 20};
Часть {10, 20}
не является параметром initializer_list
. Это просто синтаксическая форма, чтобы использовать список объектов для создания другого объекта.
int a[] = {10, 20, 30};
Еще раз, это синтаксическая форма для создания массива.
Имя для синтаксической формы – braced-init-list
.
У вас есть две разные вещи при использовании {}
- A Тип
std::initializer_list
где значения могут быть неявно преобразованы вT
- Тип, который можно инициализировать со значениями списка.
Первый тип заставляет однородный список, а второй тип – нет. В следующем примере:
struct S{ int a; string b }; void f1( S s ); void f2( int i ); void f3( std::initializer_list 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 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