C ++, возможно ли вызвать конструктор напрямую, без нового? - PullRequest
49 голосов
/ 22 марта 2010

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

Ответы [ 10 ]

77 голосов
/ 22 марта 2010

Вроде. Вы можете использовать размещение нового , чтобы запустить конструктор, используя уже выделенную память:

 #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, но выделение памяти не происходит.

16 голосов
/ 22 марта 2010

Я думаю, вы ищете новое место размещения. C ++ FAQ Lite содержит краткое описание того, как вы это делаете.Из этой записи есть несколько важных ошибок:

  1. Вы должны #include <new> использовать новый синтаксис размещения.
  2. Ваш буфер памяти должен быть правильно выровненобъект, который вы создаете.
  3. Ваша задача - вызвать деструктор вручную.
15 голосов
/ 22 марта 2010

Позвольте мне показать вам некоторый код о том, как это можно сделать, как в строительстве, так и в разрушении

#include <new>

// Let's create some memory where we will construct the object.
MyObject* obj = (MyObject*)malloc(sizeof(MyObject));

// Let's construct the object using the placement new
new(obj) MyObject();

// Let's destruct it now
obj->~MyObject();

// Let's release the memory we used before
free(obj);
obj = 0;

Надеюсь, приведенное выше резюме прояснит ситуацию.

5 голосов
/ 22 марта 2010

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

2 голосов
/ 22 марта 2010

Да, когда у вас есть собственный выделенный буфер, вы используете новое размещение. Брайан Бонди имеет хороший ответ здесь в связанном вопросе:

Что используется для "размещения новых"?

1 голос
/ 22 марта 2010

Да, используя новое размещение - как указано выше, но вы можете рассмотреть возможность использования второго класса фабрики для управления хранилищем, даже если это означает копирование объекта.memcpy () обычно дешев для небольших объектов.

1 голос
/ 22 марта 2010

Вы можете вызвать деструктор, но память не будет восстановлена, и ваш вызов будет эквивалентен вызову функции. Вы должны помнить, что под деструктором выполняется 2 вещи: разрушает объект на основе вашей спецификации и освобождает память. Поскольку ваш dtor в любом случае будет вызываться для объекта, размещенного в стеке, повторный вызов может привести к неопределенному поведению.

0 голосов
/ 09 июня 2019

Похоже, что размещение новых звонков - тренд, поэтому я стараюсь предложить альтернативу Не уверен, что это хорошо, хотя.

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 хотела подчеркнуть разницу между конструкцией и назначением. Довольно глупо, если вы спросите меня.

0 голосов
/ 26 марта 2019

Вы можете использовать следующий шаблон

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);
0 голосов
/ 05 августа 2016

На основе комментариев это работает только для компиляторов Microsoft C ++

Все просто, без 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
}
...