Ответ 1
Вы можете создать массив указателей (т.е. Point**
) и инициализировать их в 2 этапа:
-
создать массив:
PointPtr* centroids = new PointPtr[k];
-
Initialize:
for (int i=0 ; i<k ; ++i) centroids[i]=new Point(5);
Я пытаюсь передать аргументы в конструктор, но тем временем создаю массив таких объектов. Для этого я использовал следующий код:
PointPtr centroids = new Point[k](5);
Ну, это была не синтаксическая ошибка, но она не компилировалась. Я действительно не хотел жестко закодировать "5" в конструкторе по умолчанию для Point. Есть идеи о том, как я должен это делать? Спасибо!
Кстати, я уже typedef Point *PointPtr
где-то еще.
Извините, если заголовок не был точным. Я не знал, как это сделать.
Вы можете создать массив указателей (т.е. Point**
) и инициализировать их в 2 этапа:
создать массив:
PointPtr* centroids = new PointPtr[k];
Initialize:
for (int i=0 ; i<k ; ++i)
centroids[i]=new Point(5);
Я бы предложил использовать std::vector
:
std::vector<Point> v(k, Point{5});
Но вы также можете сделать это как:
Point* centroids = new Point[5]{{1}, {2}, {3}, {4}, {5}};
Если вы не можете использовать std::vector
, тогда необходимо динамически выделять массив указателей, затем динамически выделять n объектов и назначать полученную память указателям в массиве. Например:
constexpr auto ARRAYSIZE = 5;
auto x = new PointPtr[ARRAYSIZE]; // should check for memory alloc errors
for (int i = 0; i < ARRAYSIZE; ++i)
{
x[i] = new Point(5); // pass any arguments you want, remember to check if allocation was successful
}
Обратите внимание, что такие практики нахмурились, потому что вы никогда не должны использовать new
, если у вас нет веских оснований для этого (и ИМО это глупо, что вам не разрешено делать что-то надлежащим образом и преподавать хорошие практики из начало); вместо этого используйте std::vector
и интеллектуальные указатели, они должны быть в состоянии удовлетворить все ваши потребности в динамической памяти.
Примечание 1: Использование стандартной библиотеки (а именно
std::vector
в этом случае) для обработки вещей предпочтительнее!Примечание 2: Лично я бы не пошел по массиву указателей, потому что вы уничтожили локальную память.
Вы можете использовать std::allocator
:
// Create allocator object
std::allocator<Point> alloc;
// allocate storage for k Points
Point * p = alloc.allocate(k);
// Construct k Points in p
for (std::size_t i{0}; i<k; ++i)
{
alloc.construct(p+i, 5);
}
// Do stuff using p
// ...
// Destroy k objects in p
for (std::size_t i{0}; i<k; ++i)
{
alloc.destroy(p+i);
}
// Dealloacte memory
alloc.deallocate(p, k);
или вы можете обрабатывать его вручную
// allocate
Point * p = static_cast<Point*>(::operator new[](k*sizeof(Point)));
// placement new construction
for (std::size_t i{0}; i<k; ++i)
{
new((void *)(p+i)) Point{5};
}
// stuff
// destruction
for (std::size_t i{0}; i<k; ++i)
{
(p+i)->~Point();
}
// deallocation
::operator delete[](static_cast<void*>(p));
где я бы поместил обработку памяти в функции (если не в класс):
#include <new>
#include <utility>
#include <cstddef>
template<class T, class ... Args>
T * new_n(std::size_t const n, Args&& ... args)
{
T * p{ (T*)::operator new[](n*sizeof(T)) };
for (std::size_t i{ 0 }; i < n; ++i)
{
new((void*)(p + i)) T(std::forward<Args>(args)...);
}
return p;
}
template<class T>
void remove_n(T * const p, std::size_t const n)
{
for (std::size_t i{ 0 }; i < n; ++i) (p + i)->~T();
::operator delete[]((void*)p);
}
и используйте их
auto p = new_n<Point>(k, 5);
// stuff using k Points in p constructed by passing 5 to constructors
remove_n(p, k);