Почему поведение списка инициализаторов C++ для std::vector и std::array отличается?
код:
std::vector<int> x{1,2,3,4};
std::array<int, 4> y{{1,2,3,4}};
зачем мне нужны двойные фигурные скобки для std:: array?
2 ответа:
std::array<T, N>
является агрегатом: он не имеет каких-либо объявленных пользователем конструкторов, даже не один принимаяstd::initializer_list
. Инициализация с помощью фигурных скобок выполняется с помощью агрегатной инициализации, функция C++, которая была унаследована от C."старый стиль" агрегатной инициализации использует
=
:std::array<int, 4> y = { { 1, 2, 3, 4 } };
С этим старым стилем агрегатной инициализации, дополнительные фигурные скобки могут быть удалены, так что это эквивалентно к:
std::array<int, 4> y = { 1, 2, 3, 4 };
однако эти дополнительные фигурные скобки могут быть удалены только " в объявлении формы
T x = { a };
" (в C++11 §8.5.1/11), то есть, когда старый стиль есть . Это правило, разрешающее выделение скобок, не применяется для прямой инициализации списка. Сноска здесь гласит: "фигурные скобки не могут быть исключены в других случаях использования инициализации списка."есть сообщение о дефекте относительно этого ограничения:дефект CWG #1270. Если предлагаемая резолюция является принятый, brace elision будет разрешен для других форм инициализации списка, и следующие будут хорошо сформированы:
std::array<int, 4> y{ 1, 2, 3, 4 };
(наконечник шляпы для Ville Voutilainen для поиска отчета о дефекте.)
, потому что
std::vector
предлагает конструктор, который принимает вstd::initializer_list<T>
, в то время какstd::array
не имеет конструкторов и{1, 2, 3, 4}
приготовился инициализации-список является в действительности не интерпретируется какstd::initializer_list
, но агрегатная инициализация для внутреннего массива C-стиляstd::array
(вот откуда берется второй набор фигурных скобок: один дляstd::array
, один для внутреннего массива элементов C-стиля).