Как создать динамический массив из объектов класса?

Нужно создать динамический массив из объектов класса, у которого единственный конструктор принимает значение. Язык C++ без использования класса vector!

Описание класса:
class Test {
	int k;
public:
	Test(int _i) {k = _i; }
	~Test();

	void put_k(int i) {k = i; }
	int get_k() {return k; }
};

Реализация
#define COUNT_OBJ 4
int main()
{
	// Данное объявление массива не является верным, т.к. конструктору класса Test в обязательном порядке нужно передать параметр типа int
	Test *objPtr = new Test[COUNT_OBJ];

	// Со статическим объявлением массива все проще
	Test objArray[COUNT_OBJ] = {5, 6, 7, 8};

	return 0;
}
  • Вопрос задан
  • 30528 просмотров
Решения вопроса 2
@mink_h Автор вопроса
И так, нашел несколько способов:

1. Если компилятор поддерживает стандарт C++ 2011
Test *objPtr = new Test[COUNT_OBJ] {5, 6, 7, 8};

2. Реализация того, что было сказано GavriKos
Test *objPtr = (Test*)calloc(COUNT_OBJ, sizeof(Test));
memset(objPtr, 0, COUNT_OBJ * sizeof(Test));
for (int i = 0; i < COUNT_OBJ; ++i) objPtr[i].put_k(i + 5);

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

3. Вариант, представленный Rsa97 в комментариях
Test **objPtr = new Test*[COUNT_OBJ];
for (int i = 0; i < COUNT_OBJ; ++i) objPtr[i] = new Test(i + 5);

4. На мой взгляд, самая удачная реализация с использованием Placement new. На данный способ указал Игорь Иванов
Test *objPtr = static_cast<Test*>(operator new[] (COUNT_OBJ * sizeof(Test)));
for (int i = 0; i < COUNT_OBJ; ++i) new (objPtr + i) Test(i + 5);
Ответ написан
ksey3000
@ksey3000
Инженер-сетевик. Программирование-хобби.
Классический Placement new
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 6
sfi0zy
@sfi0zy
Creative frontend developer
Используйте vector и не думайте ни о чем
std::vector<Test> myTests(4, Test(777));
std::cout << myTests[0].get_k(); // 777
Ответ написан
Комментировать
GavriKos
@GavriKos
Варианты:
1) Использовать vector
2) Выделить просто участок памяти (malloc и иже с ними), а потом заполнить его в цикле
3) Не использовать конструктор с параметром, а сделать метод типа Initialize.
Ответ написан
Вы только лишь выделяете память. Инициализировать необходимо вручную.
Ответ написан
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Test **objPtr = new (Test *)[COUNT_OBJ];
for (int i = 0; i < COUNT_OBJ; i++)
    objPtr[i] = new Test(i);
Ответ написан
@asapelkin
А что если сделать массив не объектов этого класса, а массив указателей на обьекты? А потом в цикле инициализировать каждый элемент уже с вызовом конструктора.
А вообще, используйте вектор, какие проблемы.
Ответ написан
@Mercury13
Программист на «си с крестами» и не только
Операция присваивания или перемещения есть? Пускай даже созданная автоматически? Если есть — вот, смотрите.
#include <iostream>
#include <vector>

class Test {
  int k;
public:
  Test(int _i) {k = _i; }

  void put_k(int i) {k = i; }
  int get_k() {return k; }
};


struct TestWrapper {
    Test payload;
    TestWrapper() : payload(0) {}
    TestWrapper(int i) : payload(i) {}
    TestWrapper(const Test& i) : payload(i) {}
};

int main()
{
    Test test(10);
    std::vector<TestWrapper> v;
    v.push_back(test);
    std::cout << v[0].payload.get_k() << std::endl;
    return 0;
}


Если нет — тогда динамический массив так просто работать не может (фишка динамического массива — заводить новый массив и копировать информацию из старого). Только использованием умных указателей.
#include <iostream>
#include <vector>
#include <memory>


class Test {
  int k;
public:
  Test(int _i) {k = _i; }
  Test& operator=(const Test&) = delete;
  Test& operator=(Test&&) = delete;

  void put_k(int i) {k = i; }
  int get_k() {return k; }
};


int main()
{
    std::vector<std::unique_ptr<Test>> v;
    v.push_back(std::unique_ptr<Test>(new Test(10)));
    std::cout << v[0]->get_k() << std::endl;
    return 0;
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы