Инициализация массива-члена в инициализаторе конструктора - PullRequest
88 голосов
/ 30 октября 2010
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 что-то особенное об инициализации агрегатов (включая массивы) в инициализаторах ctor?Или недействительность приведенного выше кода является следствием некоторых других правил?
  3. Решают ли списки инициализаторов C ++ 0x проблему?

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

Ответы [ 6 ]

51 голосов
/ 30 октября 2010
  1. Как я могу делать то, что хочу (то есть инициализировать массив в конструкторе (не назначая элементы в теле)). Это вообще возможно?

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

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

Mem-инициализатор использует прямую инициализацию. И правила пункта 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 */
};
28 голосов
/ 30 октября 2010

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

Мне кажется, что Роджер Пэйт ошибается в предполагаемых ограничениях инициализации агрегата C ++ 0x, но мне лень его искать или проверять, и это не имеет значения, не так ли? РЕДАКТИРОВАТЬ : Роджер говорил о "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}};
6 голосов
/ 30 октября 2010

Обходной путь:

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()) {}
};
3 голосов
/ 30 октября 2010
  1. Нет, к сожалению.
  2. Вы просто не можете так, как хотите, так как это не разрешено грамматикой (подробнее ниже).Вы можете использовать только ctor-подобную инициализацию, и, как вы знаете, она не доступна для инициализации каждого элемента в массивах.
  3. Я так считаю, поскольку они обобщают инициализацию по всем направлениям многими полезными способами.Но я не уверен в деталях.

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

T var = {...};
1 голос
/ 12 мая 2014

Как насчет

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

Прекрасно компилируется на g ++ 4.8

0 голосов
/ 29 июня 2017

Вы хотите инициализировать массив целых в вашем конструкторе? Укажите это на статический массив.

class C 
{
public:
    int *cArray;

};

C::C {
    static int c_init[]{1,2,3};
    cArray = c_init;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...