Инициализация массива участника в инициализаторе конструктора
-
27-09-2019 - |
Вопрос
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};
Вопросы
- Как я могу сделать то, что я хочу сделать (то есть инициализация Массив в конструкторе (не назначает элементы в организме)). Это даже возможно?
- Стандарт C ++ 03 говорит что-то особенное в инициализации агрегатов (включая массивы) в инициализаторах CTOR? Или неверность вышеуказанного кода является следствием некоторых других правил?
- Списки инициализатора C ++ 0x решают проблему?
PS. Пожалуйста, не упоминайте векторы, Boost :: Armers и их превосходство к массивам, которые я хорошо знаю.
Решение
- Как я могу сделать то, что хочу сделать (то есть инициализировать массив в конструкторе (не назначать элементы в организме)). Это даже возможно?
Да. Это использует структуру, которая содержит массив. Вы говорите, что вы уже знаете об этом, но тогда я не понимаю вопрос. Таким образом, вы делать Инициализируйте массив в конструкторе, без назначений в организме. Это то, что boost::array
делает.
Стандарт C ++ 03 говорит что-то особенное в инициализации агрегатов (включая массивы) в инициализаторах CTOR? Или неверность вышеуказанного кода является следствием некоторых других правил?
МЕМ-инициализатор использует прямую инициализацию. И правила пункта 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 не обеспечивает прямой синтаксис для чего-либо, кроме обнуления (или для элементов без стручки, инициализации значения). За то, что вы просто пишете C(): arr() {}
.
Я вещь Roger Pate неверна о предполагаемых ограничениях совокупной инициализации 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}};
Обходной путь:
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()) {}
};
- Нет, к сожалению.
- Вы просто не можете так, как вы хотите, так как он не допускается грамматикой (более ниже). Вы можете использовать только CTOR-подобную инициализацию, и, как вы знаете, это недоступно для инициализации каждого элемента в массивах.
- Я так верю, поскольку они обобщают инициализацию через доску во многих полезных способах. Но я не уверен в деталях.
В 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;
}