Инициализация массива-члена в инициализаторе конструктора

class C { public: C() : arr({1,2,3}) //doesn't compile {} /* C() : arr{1,2,3} //doesn't compile either {} */ private: int arr[3]; }; 

Я считаю, что причина в том, что массивы могут быть инициализированы только с помощью = синтаксиса, то есть:

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

Вопросов

  1. Как я могу сделать то, что я хочу сделать (то есть инициализировать массив в конструкторе (не назначая элементы в теле)). Возможно ли это?
  2. Означает ли стандарт C ++ 03 что-то особенное в инициализации инициализации агрегатов (включая массивы)? Или недействительность вышеуказанного кода является следствием некоторых других правил?
  3. Перечислены ли списки инициализаторов C ++ 0x?

PS Пожалуйста, не указывайте векторы, boost :: array и их превосходство в массивах, о которых я хорошо знаю.

  1. Как я могу сделать то, что я хочу сделать (то есть инициализировать массив в конструкторе (не назначая элементы в теле)). Возможно ли это?

Да. Он использует структуру, содержащую массив. Вы говорите, что уже знаете об этом, но тогда я не понимаю вопроса. Таким образом, вы инициализируете массив в конструкторе без назначений в теле. Это то, что делает boost::array .

Означает ли стандарт C ++ 03 что-то особенное в инициализации инициализации агрегатов (включая массивы)? Или недействительность вышеуказанного кода является следствием некоторых других правил?

Мем-инициализатор использует прямую инициализацию. И правила пункта 8 запрещают подобные вещи. Я не совсем уверен в следующем случае, но некоторые компиляторы действительно позволяют это делать.

 struct A { char foo[6]; A():foo("hello") { } /* valid? */ }; 

См. Этот GCC PR для получения дополнительной информации.

Перечислены ли списки инициализаторов C ++ 0x?

Да, так и есть. Я думаю, что ваш синтаксис недействителен. Вы должны использовать фигурные скобки непосредственно для запуска инициализации списка

 struct A { int foo[3]; A():foo{1, 2, 3} { } A():foo({1, 2, 3}) { } /* invalid */ }; 

C ++ 98 не обеспечивает прямой синтаксис для чего угодно, кроме обнуления (или для не-POD-элементов, инициализации значения) массива. Для этого вы просто пишете C(): arr() {} .

Я считаю, что Roger Pate ошибается в отношении предполагаемых ограничений инициализации C ++ 0x, но я слишком ленив, чтобы посмотреть его или проверить, и это не имеет значения, не так ли? EDIT : Роджер говорил о «C ++ 03», я неправильно читал его как «C ++ 0x». Прости, Роджер. ☺

Обходной путь C ++ 98 для вашего текущего кода состоит в том, чтобы обернуть массив в struct и инициализировать его из статической константы этого типа. В любом случае данные должны находиться где-то. С манжетой он может выглядеть так:

 class C { public: C() : arr( arrData ) {} private: struct Arr{ int elem[3]; }; Arr arr; static Arr const arrData; }; C::Arr const C::arrData = {{1, 2, 3}}; 

Временное решение:

 template struct simple_array { // like std::array in C++0x T arr[N]; }; class C : private simple_array { static simple_array myarr() { simple_array arr = {1,2,3}; return arr; } public: C() : simple_array(myarr()) {} }; 
  1. Нет, к сожалению.
  2. Вы просто не можете так, как хотите, поскольку это не допускается грамматикой (более подробно). Вы можете использовать только инициализацию ctor-like, и, как вы знаете, это не доступно для инициализации каждого элемента в массивах.
  3. Я так считаю, поскольку они обобщают инициализацию по всем направлениям многими полезными способами. Но я не уверен в деталях.

В C ++ 03 агрегатная инициализация применяется только с синтаксисом, подобным приведенному ниже, который должен быть отдельным оператором и не вписывается в инициализатор ctor.

 T var = {...}; 

Как насчет

 ... C() : arr{ {1,2,3} } {} ... 

?

Компилирует отлично на g ++ 4.8

Вы хотите инициализировать массив ints в своем конструкторе? Направьте его на статический массив.

 class C { public: int *cArray; }; C::C { static int c_init[]{1,2,3}; cArray = c_init; } 
Давайте будем гением компьютера.