Как динамически объявлять массив объектов с конструктором в С++
Мне было интересно, можно ли создать массив объектов, когда объект нуждается в вещах, переданных ему для конструктора. Я хочу что-то вроде этого:
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);
Я бы использовал векторы и такие, но мой учитель сказал нам использовать базовые массивы, когда это возможно. Вышеупомянутое решение, которое я действительно получил от некоторого кода, написал мой учитель. Спасибо всем за вашу помощь!
Ответы
Ответ 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);
}