Инициализация массива элементов в инициализаторе конструктора
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};
вопросы
- как я могу сделать то, что я хочу сделать (что
есть инициализации массив в a
конструктор (не присваивая элементы
в теле.)) Это вообще возможно? - стандарт C++03 говорит что-нибудь особенное об инициализации агрегатов (включая массивы) в инициализаторах ctor? Или недействительность вышеуказанного код является следствием некоторых других правил?
- списки инициализаторов C++0x решают проблему?
П. С. пожалуйста, не упоминайте векторы, boost::arrays и их превосходство над массивами, о которых я хорошо знаю.
6 ответов:
- как я могу сделать то, что я хочу сделать (то есть, инициализировать массив в конструкторе (не назначая элементы в теле)). Это вообще возможно?
да. Он использует структуру, которая содержит массив. Вы говорите, что уже знаете об этом, но тогда я не понимаю вопроса. Таким образом, вы 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 */ };
C++98 не предоставляет прямого синтаксиса ни для чего, кроме обнуления (или для не-POD элементов, инициализации значений) массива. Для этого вы просто пишете
C(): arr() {}.Я думаю, что Роджер Пэйт ошибается в предполагаемых ограничениях инициализации агрегата 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<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 = {...};
вы хотите инициализировать массив ints в вашем конструкторе? Наведите его на статический массив.
class C { public: int *cArray; }; C::C { static int c_init[]{1,2,3}; cArray = c_init; }
Comments