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

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};

Вопросы

  • Как я могу делать то, что хочу (что is, инициализировать массив в конструктор (не назначая элементы в организме)). Возможно ли это?
  • Знает ли стандарт С++ 03 что-то особенное об инициализации агрегатов (включая массивы) в инициализаторах ctor? Или недействительность вышеуказанного кода является следствием некоторых других правил?
  • Реализуют ли списки инициализаторов С++ 0x?

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

Ответ 1

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

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

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

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

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

Подробнее см. этот GCC PR.

Реализовывают ли списки инициализаторов С++ 0x?

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

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

Ответ 2

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

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

Обходной путь С++ 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}};

Ответ 3

Обход проблемы:

template<class T, size_t N>
struct simple_array { // like std::array in C++0x
   T arr[N];
};


class C : private simple_array<int, 3> 
{
      static simple_array<int, 3> myarr() {
           simple_array<int, 3> arr = {1,2,3};
           return arr;
      }
public:
      C() : simple_array<int, 3>(myarr()) {}
};

Ответ 4

  • Нет, к сожалению.
  • Вы просто не можете так, как хотите, поскольку это не допускается грамматикой (более подробно). Вы можете использовать только инициализацию с помощью ctor и, как вы знаете, недоступную для инициализации каждого элемента в массивах.
  • Я так считаю, поскольку они обобщают инициализацию по всем направлениям многими полезными способами. Но я не уверен в деталях.

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

T var = {...};

Ответ 5

Как насчет

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

?

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

Ответ 6

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

class C 
{
public:
    int *cArray;

};

C::C {
    static int c_init[]{1,2,3};
    cArray = c_init;
}