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

С++, можно ли вызвать конструктор напрямую, без новых?

Могу ли я вызвать конструктор явно, не используя 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
4b9b3361

Ответ 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

Буквально, НЕТ, вы не можете сделать это без "нового" ключевого слова. Просмотрите все ответы о размещении нового для использования ключевого слова "новое", чтобы вызвать конструктор без фактического выделения памяти.

Ответ 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
}