2014-04-09 6 views
4

Я хочу использовать двумерный массив постоянного размера как член класса в C++. Однако у меня проблемы с инициализацией в конструкторе.C++: инициализация многомерного массива в конструкторе

Вот мои неработающие попытки:

1.)

class A { 
public: 
    int a[2][2]; 
    A(); 
}; 

A::A() { 
a = {{1,2},{2,4}}; 
} 

Урожайность: error: assigning to an array from an initializer list

2.)

class A { 
public: 
    int a[2][2]; 
    A(); 
}; 

A::A() { 
int b[2][2] = {{1,2},{2,4}}; 
a = b; 
} 

Урожайность: invalid array assignment

3.)

class A { 
public: 
    int **a; 
    A(); 
}; 

A::A() { 
int b[2][2] = {{1,2},{2,4}}; 
a = b; 
} 

выходы: cannot convert ‘int [2][2]’ to ‘int**’ in assignment

Я родом из C фоне. Я знаю, что могу использовать std::vector, и я знаю об этом недостатках, но поскольку это упражнение для меня, я хотел бы знать, как заставить его работать с обычными массивами. Я должен добавить, что я хочу продолжить работу над этим массивом позже. Я хочу изменить сохраненные значения, но не размер. Возможно, это имеет значение (я понял, что const в нужном месте может помочь?).

ответ

6

Если у вас есть C++ 11, вы можете использовать этот синтаксис в определении конструктора:

A() : a{{1,2}, {3, 4}} {} 

Если у вас нет C++ 11, вам нужно будет придерживаться злыми старых способов:

A() { 
    a[0][0] = 1; 
    // etc 
} 

Первый пример также использует конструкцию или init-list, которые всегда должны использоваться для инициализации элементов вместо их инициализации в теле конструктора.

+1

Как я понимаю, используемый здесь синтаксис является нестандартным, расширением языка g ++. –

+0

@ Cheersandhth.-Alf Я тестировал это как gcc, так и clang, используя '-std = C++ 11' (в отличие от' std = gnu11'), и оба приняли его. 'clang' отклонил' a ({{1,2}, {3, 4}}) 'хотя в качестве расширения GNU. – pmr

+0

@ Cheersandhth.-Alf Попробуйте скомпилировать этот код и свой флаг '-pedantic-errors' и ... – Constructor

0

Ваш первый вариант очень близок к правому C++ 11 синтаксиса:

A::A() 
    : a{{1,2},{2,4}} 
{ 
} 
+1

Это НКУ Расширение GNU. Отбросьте внешние парсеры. – pmr

+0

@pmr Спасибо. На самом деле это была опечатка. :-) – Constructor

0

В дополнении к предыдущим ответам (вы, ребята, так быстро):

То, что вы пытались сделать в случае, если 1 и 2 является array assignment, не допускается, как говорит составитель;

Но я хотел бы обратить ваше внимание на ваш третий случай, это серьезное заблуждение, особенно исходящее от C, как вы говорите.

Присвоение a указателя на локальную переменную?

+0

Только для меня и для полного понимания: это сделало бы '** a'' NULL' после того, как конструктор закончил? Я тоже не профессионал в 'C'. – ravenfrost

+0

Нет, нет. Аналогия заключается в том, что 'b' существует только там, где он был объявлен (конструктор), поэтому, если вы берете его адрес, когда функция заканчивается,' a' будет по-прежнему иметь какое бы то ни было значение, но мы не можем гарантировать, что будет там. Программа может использовать этот адрес для другой цели. Скорее всего, если вы позже попытаетесь получить доступ к тому, что 'a' указывает на внешнюю функцию, появится ошибка о недопустимой памяти или будет прочитано некоторое недостоверное значение. – Kahler

+0

Хорошо, теперь я вижу. Спасибо, что объяснил это мне. – ravenfrost

1

Попробуйте, это работает для двумерного массива (в стандартном C++):

class A { 
public: 
    int a[2][2]; 
    A(); 
}; 


typedef struct{ int a[4]; } array_t; 

A::A() { 

int at[2][2] = {{1,2},{2,4}}; 

*(array_t*)a = *(array_t*)at; 

} 

Ciao Angelo

+0

Я думаю, что назначение - неопределенное поведение, хотя вы можете сохранить ситуацию, используя «memcpy» или эквивалент. –

+0

Этот метод заставляет компилятор использовать оператор присваивания для указанного массива (поддерживается для стандартных структур). Естественно, это справедливо только тогда, когда размер операндов равен. Я использую этот пример, чтобы показать силу литья языка С. Тем не менее, я принимаю ваш комментарий, и я задам новый вопрос об этом аргументе, поэтому у нас могут быть другие мнения о коде aove. Благодарю. – AngeloDM

+0

UB приходит, прежде чем вы доберетесь до этого. Нельзя идентифицировать структуру как 'int [2] [2]'. (В стандарте перечислены типы, которые могут быть сглажены с помощью каких типов, а этого нет в списке).Кроме того, возможно, что 'at' может быть неправильно выровнено для' array_t * '(мне нужно будет проверить формулировку требований к выравниванию, чтобы проверить это) –

0

различных многомерного массива в конструкторе пример:

// int array1[1]; 
A() : array1{0} {} 

// int array2[2][2]; 
A() : array2{{0}} {} 

// int array3[3][3][3]; 
A() : array3{{{0}}} {} 
Смежные вопросы