Инициализация массива-члена в инициализаторе конструктора
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;
}