Почему поведение списка инициализаторов 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-стиля).