57

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
4

9 回答 9

83

有点。您可以使用placement 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关键字,但没有进行内存分配。

于 2010-03-22T17:45:26.357 回答
17

我认为您正在寻找新的展示位置。C++ FAQ Lite很好地总结了你是如何做到这一点的。此条目有一些重要的陷阱:

  1. 您应该#include <new>使用放置新语法。
  2. 您的内存缓冲区需要为您正在创建的对象正确对齐。
  3. 手动调用析构函数是你的工作。
于 2010-03-22T17:47:35.523 回答
17

让我向您展示一些有关如何完成它的代码,包括构造和破坏

#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;

我希望上面的总结能让事情更清楚。

于 2010-03-22T18:06:13.157 回答
6

从字面上看,不,没有“new”关键字你就做不到。有关使用“new”关键字调用构造函数而不实际分配内存的方式,请参阅有关放置 new 的所有答案。

于 2010-03-22T17:57:27.980 回答
2

是的,当您拥有自己分配的缓冲区时,您可以使用placement new。布赖恩邦迪在一个相关问题中有一个很好的回应:

“安置新”有什么用?

于 2010-03-22T17:47:32.777 回答
1

你可以调用析构函数,但不会回收内存,你的调用就相当于函数调用。您必须记住,在析构函数下面做了两件事:根据您的规范破坏对象,并回收内存。由于无论如何都会为分配在堆栈上的对象调用 dtor,因此调用它两次可能会导致未定义的行为。

于 2010-03-22T17:47:27.130 回答
1

是的,使用placement new - 如上所述,但您可能会考虑使用第二个工厂类来管理存储,即使这意味着复制对象。memcpy() 对于小对象来说通常很便宜。

于 2010-03-22T17:53:44.463 回答
0

您可以使用以下模板

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);
于 2019-03-26T02:37:45.593 回答
-2

根据评论,这仅适用于 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
}
于 2016-08-05T00:12:57.023 回答