Ниже приводится цитата из Эффективный Современный C ++ (стр. 55):
«Предположим, что вы используете пустой набор скобок для создания объекта, который поддерживает конструктор по умолчанию, а также поддерживает конструкцию std :: initializer_list. Что означают ваши пустые скобки? И т. Д. Правило состоит в том, что вы получаете конструкцию по умолчанию».
Я попробовал это с std :: array:
std::array<int, 10> arr{};
и получил предупреждение от g ++ (версия 4.8.2):
предупреждение: отсутствует инициализатор для члена ‘std :: array<int, 10ul> :: _ M_elems ’
что является предупреждением при попытке построить std::array
из пустого std::initializer_list
(увидеть Почему я могу инициализировать обычный массив из {}, но не std :: array для обсуждения этого предупреждения).
Итак, почему вышеприведенная строка кода не интерпретируется как вызов конструктора по умолчанию?
Это потому станд :: массив является совокупностью и, следовательно, агрегатная инициализация выполняется это покрыто проект стандарта C ++ 11 раздел 8.5.4
[Dcl.init.list] который говорит:
Инициализация списка объекта или ссылки типа T определяется следующим образом:
Если список инициализаторов не имеет элементов и T является типом класса с конструктором по умолчанию, объект
значение инициализации.В противном случае, если T является агрегатом, выполняется агрегатная инициализация (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
и мы можем увидеть, если это не агрегат, то список можно продолжить:
- В противном случае, если T является специализацией std :: initializer_list, объект initializer_list имеет вид
построен как описано ниже и используется для инициализации объекта в соответствии с правилами для инициализации
объекта из класса того же типа (8.5).- В противном случае, если T является типом класса, учитываются конструкторы. Применимые конструкторы перечислены
и лучший выбирается через разрешение перегрузки (13.3, 13.3.1.7). Если сужение конверсии (см.
ниже) требуется преобразовать любой из аргументов, программа некорректно сформирована.
Мы можем подтвердить std::array
это агрегат из раздела 23.3.2.1
[Array.overview]:
Массив — это агрегат (8.5.1), который можно инициализировать с помощью
синтаксисarray<T, N> a = { initializer-list };
где initializer-list — разделенный запятыми список до N элементов
чьи типы обратимы в Т.
раздел 8.5.1
ссылка на 8.5.1
сводные показатели [Dcl.init.aggr] и говорит:
Когда агрегат инициализируется списком инициализаторов, как указано
в 8.5.4 элементы списка инициализатора принимаются как
инициализаторы для элементов совокупности, в возрастающем индексе
или заказ участника […]
и мы идем полный круг обратно в раздел 8.5.4
вот где мы начали.