С++, можно ли вызвать конструктор напрямую, без новых?
Могу ли я вызвать конструктор явно, не используя new
, если у меня уже есть память для объекта?
class Object1{
char *str;
public:
Object1(char*str1){
str=strdup(str1);
puts("ctor");
puts(str);
}
~Object1(){
puts("dtor");
puts(str);
free(str);
}
};
Object1 ooo[2] = {
Object1("I'm the first object"), Object1("I'm the 2nd")
};
do_smth_useful(ooo);
ooo[0].~Object1(); // call destructor
ooo[0].Object1("I'm the 3rd object in place of first"); // ???? - reuse memory
Ответы
Ответ 1
Сорт. Вы можете использовать размещение new для запуска конструктора с использованием уже выделенной памяти:
#include <new>
Object1 ooo[2] = {Object1("I'm the first object"), Object1("I'm the 2nd")};
do_smth_useful(ooo);
ooo[0].~Object1(); // call destructor
new (&ooo[0]) Object1("I'm the 3rd object in place of first");
Итак, вы по-прежнему используете ключевое слово new
, но распределение памяти не происходит.
Ответ 2
Я думаю, вы ищете Placement New. С++ FAQ Lite содержит хорошее резюме того, как вы это делаете. Из этой записи есть несколько важных ошибок:
- Вы должны использовать
#include <new>
для использования синтаксиса нового места размещения.
- Ваш буфер памяти должен быть правильно выровнен для создаваемого объекта.
- Это ваша задача вручную вызвать деструктор.
Ответ 3
Позвольте мне показать вам некоторый код о том, как это можно сделать, как в строительстве, так и в разрушении
#include <new>
// Let create some memory where we will construct the object.
MyObject* obj = (MyObject*)malloc(sizeof(MyObject));
// Let construct the object using the placement new
new(obj) MyObject();
// Let destruct it now
obj->~MyObject();
// Let release the memory we used before
free(obj);
obj = 0;
Надеюсь, что вышеприведенное резюме делает все более ясным.
Ответ 4
Буквально, НЕТ, вы не можете сделать это без "нового" ключевого слова. Просмотрите все ответы о размещении нового для использования ключевого слова "новое", чтобы вызвать конструктор без фактического выделения памяти.
Ответ 5
Да, когда у вас есть собственный выделенный буфер, вы используете новое место размещения. Брайан Бонди имеет хороший ответ здесь по смежному вопросу:
Что используется для "размещения нового" ?
Ответ 6
Вы можете вызвать деструктор, но память не будет восстановлена, и ваш вызов будет эквивалентен вызову функции. Вы должны помнить, что под деструктором делаются 2 вещи: уничтожает объект на основе вашей спецификации и восстанавливает память. Поскольку dtor будет вызываться в любом случае для объекта, выделенного в стеке, вызов его дважды может привести к поведению undefined.
Ответ 7
Да, используя новое место размещения - как указано выше, но вы можете рассмотреть возможность использования второго класса factory для управления хранилищем, даже если это означает копирование объекта. memcpy() обычно дешево для небольших объектов.
Ответ 8
Вы можете использовать следующий шаблон
template <typename T, typename... Args>
inline void InitClass(T &t, Args... args)
{
t.~T();
new (&t) T(args...);
}
использование:
struct A
{
A() {}
A(int i) : a(i) {}
int a;
} my_value;
InitClass(my_value);
InitClass(my_value, 5);
Ответ 9
Похоже, что его размещение новых звонков является тенденцией, поэтому я стараюсь предложить альтернативу. Не уверен, что это хорошо, хотя.
struct a
{
std::vector<int> i{ 10, 20, 30, 40 };
};
int main()
{
a *i = // allocate
*i = a(); // calls ctor, calls copy operator, calls dtor
// in principle.
}
Я с подозрением отношусь к этому маршруту из-за всех добавленных вызовов функций. Даже если это возможно, компилятор оптимизирует их.
Некоторые говорят, что конструкторы безымянные. Это явно не правда; Я думаю, что команда cpp хотела подчеркнуть разницу между конструкцией и назначением. Довольно глупо, если вы спросите меня.
Ответ 10
Основываясь на комментариях, это работает только для компиляторов Microsoft С++
Совершенно просто, без new
:
imguistate = (int *)malloc(ImGui::GetInternalStateSize());
memset(imguistate, 0, ImGui::GetInternalStateSize());
((ImGuiState *)imguistate)->ImGuiState::ImGuiState();
Это работает с любым классом:
class SomeClass {
public:
SomeClass() {
printf("Called constructor\n");
}
};
int main () {
SomeClass *someclass = new SomeClass;
someclass->SomeClass::SomeClass(); // call constructor again
}