Подтвердить что ты не робот

Как динамически объявлять массив объектов с конструктором в С++

Мне было интересно, можно ли создать массив объектов, когда объект нуждается в вещах, переданных ему для конструктора. Я хочу что-то вроде этого:

MyClass *myVar;
myVar = new MyClass[num];  // I would like to specify the array size after declaration
int i = 0;
for(i = 0;i < num;i++)
   myVar[i] = new MyClass(0,0);  // I would also like to populate the array with new objects

Я знаю, что это работает:

MyClass *myVar;
myVar = new MyClass[num];

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

EDIT: Я узнал, как это сделать с использованием массивов. Вот как я это сделал:

MyClass **myVar;
myVar = new MyClass *[num];
for(i = 0;i < num;i++)
   myVar[0] = new MyClass(0,0);

Я бы использовал векторы и такие, но мой учитель сказал нам использовать базовые массивы, когда это возможно. Вышеупомянутое решение, которое я действительно получил от некоторого кода, написал мой учитель. Спасибо всем за вашу помощь!

4b9b3361

Ответ 1

MyClass *myVar;
myVar = new MyClass[num];

На самом деле в этой форме вы не можете вызвать конструктор, который принимает параметр (ы). Спецификация языка не допускается.

Однако, если вы используете std::vector, который я рекомендую вам использовать, вы можете создать векторный вызов конструктора, отличного от стандартного, как:

#include <vector> //header file where std::vector is defined

std::vector<MyClass>  arr(num, MyClass(10,20));

Он создает вектор элементов num, каждый элемент создается вызовом copy-constructor класса, передавая ему MyClass(10,20).

Вектор также хорош, потому что теперь вам не нужно самостоятельно управлять памятью. Ни ручное распределение, ни ручное освобождение. Кроме того, вы можете узнать количество элементов, вызвав arr.size() в любое время. Вы всегда знаете, сколько элементов содержит вектор. Вы также можете добавлять элементы в любое время, просто вызывая .push_back() функцию-член как:

arr.push_back(MyClass(20,30)); 

Теперь вы можете получить доступ к элементам, так же, как к массиву доступа, например, с помощью индекса:

f(arr[i]); // 0 <= i < arr.size();

Кроме того, вы можете использовать итераторы, которые облегчают идиоматическое программирование, позволяя вам использовать различные алгоритмические функции из заголовка <algorithm> как:

#include <algorithm> //header file where std::for_each is defined

std::for_each(arr.begin(), arr.end(), f);

где f - это функция, которая принимает один аргумент типа MyClass& (или MyClass const &) в зависимости от того, что вы хотите сделать в f.

В С++ 11 вы можете использовать lambda как:

std::for_each(arr.begin(), arr.end(), [](const MyClass & m)
                                      {
                                           //working with m 
                                      });

Ответ 2

В С++ 0x работает эта грамматика, которая может вызывать конструктор не по умолчанию в новом выражении:

MyClass *myVar;
myVar = new MyClass[2]{{10, 20},{20, 30}};

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

Векторный подход будет лучше, как показано в ответе Наваза.

Ответ 3

Один из способов, который я сделал в прошлом, - использовать двойной указатель.

MyClass ** myvar;
myvar = new Myclass*[num]
for(int i = 0; i < 4; i++){
*(myvar+i) = new Myclass(i);}

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

Ответ 4

На самом деле вы можете использовать новое место размещения для этого:

MyClass * myVar;
myVar = reinterpret_cast<MyClass *>(new char[num * sizeof(MyClass)]);
int i = 0;
for (i = 0; i < num; i++) {
    new(&myVar[i]) MyClass(0,0);
}

Ответ 5

Вы также можете сделать что-то подобное:

MyClass *myVar[num];

for(int i = 0; i < num; i += 1)
{
    myVar[i] = new MyClass(0, 0);
}