C ++,是否可以直接调用构造函数,而不需要新的?

时间:2010-03-22 17:44:20

标签: c++ constructor placement-new

如果我已经有对象的内存,我可以显式调用构造函数而不使用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 个答案:

答案 0 :(得分:76)

排序。您可以使用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关键字,但不会进行内存分配。

答案 1 :(得分:15)

我认为您正在寻找Placement New。 C++ FAQ Lite总结了你如何做到这一点。这个条目有一些重要的问题:

  1. 您应该#include <new>使用展示位置新语法。
  2. 您的内存缓冲区需要与您正在创建的对象正确对齐。
  3. 手动调用析构函数是你的工作。

答案 2 :(得分:15)

让我向您展示一些关于如何在构造和破坏方面完成的代码

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

我希望上述摘要能让事情更加清晰。

答案 3 :(得分:5)

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

答案 4 :(得分:2)

是的,当你有自己的分配缓冲区时,你可以使用placement new。 Brian Bondy在一个相关的问题中得到了很好的回应:

What uses are there for "placement new"?

答案 5 :(得分:1)

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

答案 6 :(得分:1)

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

答案 7 :(得分: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);

答案 8 :(得分:-1)

它的新呼叫放置似乎是趋势,所以我尝试提供一种替代方法。不确定是否很好。

pip3

由于所有已添加的函数调用,我对此路径感到怀疑。即使编译器有可能将其优化掉。

有人说构造函数是无名的。那显然不是事实;我认为cpp团队想强调构造和任务之间的区别。如果你问我,那真是愚蠢。

答案 9 :(得分:-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
}