2014-02-19 4 views
1

Я пытаюсь создать массив объектов nxn, но я не знаю, где назвать их конструкторы. Вот мой код:Конструкция объекта C++ в многомерном динамическом массиве

class obj { 
    private: int x; 
    public: obj(int _x) { x = _x; } 
}; 

int main(int argc, const char* argv[]) { 

    int n = 3; //matrix size  

    obj** matrix = new obj*[n]; 
    for(int i = 0; i < n; i++) 
    matrix[i] = new obj[n]; 

    return 0; 
} 

ответ

3

Если требуется только вызов конструктора по умолчанию, ваш код уже вызывает его.

Для не-конструктор по умолчанию добавить вложенный цикл, как это:

for(int i = 0; i < n; i++) { 
    matrix[i] = new obj[n]; 
    for (int j = 0 ; j != n ; j++) { 
     matrix[i][j] = obj(arg1, arg2, arg3); // Non-default constructor 
    } 
} 

Лучший подход заключается в использовании std::vector из obj если не требуется полиморфное поведение, или смарт-указатели на obj если вам нужно полиморфное поведение.

+0

является необходимым использовать второй цикл в вашем фрагменте кода? эта строка 'matrix [i] = new obj [n];' сама выделяет 'n' объекты класса' obj', и делая это 'n' раз, он выделяет полную nxn-матрицу – mangusta

+0

@mangusta. Вы правы, я ошибался число звездочек, считая, что OP имеет матрицу указателей, когда на самом деле он этого не делает. Благодаря! – dasblinkenlight

+0

oh, поэтому для конструктора, отличного от по умолчанию, мы должны создать объект-мудрый?не можем ли мы сделать это в распределении массива, как 'obj() []'? я не слышал об этом, поэтому я прошу только прояснить ситуацию :) – mangusta

0

Если вы действительно хотите отключить управление памятью низкого уровня, то вы не можете - форма массива new не позволяет передавать аргументы конструкторам объектов. Лучшее, что вы могли бы сделать, это позволить им создавать по умолчанию (добавив конструктор в ваш класс, если это необходимо), а затем выполнить цикл и переназначить их. Это утомительно и подвержено ошибкам.

Я предлагаю использовать классы более высокого уровня; для динамических массивов, использовать вектор:

std::vector<std::vector<obj>> matrix(n); 
for (auto & row : matrix) { 
    row.reserve(n); 
    for (size_t i = 0; i < n; ++n) { 
     row.emplace_back(/* constructor argument(s) here */); 
    } 
} 

В качестве бонуса, RAII означает, что вам не нужно, чтобы удалить все Распределения самостоятельно, и это не будет утечка памяти, если все это не удается.

+0

На самом деле вы можете построить элементы массива на месте с новым синтаксисом размещения (см. Мой ответ). – cmaster

+0

@cmaster: В самом деле, вы можете пойти дальше по кроличьей ручке ручного управления памятью и, по сути, переосмыслить «std :: vector» (помня о том, чтобы явно уничтожить каждый объект, помимо освобождения памяти, как только вы закончите с ним). Я не собирался это предлагать, но это приведет к безумию. –

0

dasblinkenlight уже дал неплохой ответ, однако есть второй способ сделать это, что более эффективно. Потому что, если вы делаете (код взят из его ответа)

matrix[i] = new obj[n]; 
for (int j = 0 ; j != n ; j++) { 
    matrix[i][j] = obj(arg1, arg2, arg3); // Non-default constructor 
} 

произойдет следующее:

  1. памяти для n объектов выделяется.

  2. Все объекты n по-умолчанию построены.

  3. Для каждого объекта в стек создается пользовательский объект.

  4. Этот объект в стеке копируется в выделенный объект.

  5. Объект в стеке разрушен.

Очевидно, что гораздо больше, чем было бы необходимо (хотя и совершенно правильно).

Вы можете обойти эту проблему с помощью размещения нового синтаксиса:

matrix[i] = (obj*)new char[n*sizeof obj]; //Allocate only memory, do not construct! 
for (int j = 0 ; j != n ; j++) { 
    new (&matrix[i][j]) obj(arg1, arg2, arg3); // Non-default constructor called directly on the object in the matrix. 
} 
Смежные вопросы