为什么析构函数不会在放置新的“隐式调用”?

时间:2009-06-20 19:19:25

标签: c++

如本网站所述...... http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.10 但我没有找到原因,为什么我们应该明确地称之为目的地?

6 个答案:

答案 0 :(得分:10)

通常,new ed对象在调用delete时被破坏。删除永远不会被调用为新的,所以你必须弄清楚何时自己破坏对象,并明确地这样做。

答案 1 :(得分:10)

您可以将其视为删除调用,但由于您使用了placement new,因此您不希望使用delete,因为它会尝试释放内存。如果您希望自动调用它,可以使用RAII

// Could use a templated version, or find an existing impl somewhere:
void destroy_fred(Fred* f) {
   f->~Fred();
}

void someCode()
{
   char memory[sizeof(Fred)];
   void* p = memory;
   boost::shared_ptr<Fred> f(new(p) Fred(), destroy_fred);

   // ...

   // No need for an explicit destructor, cleaned up even during an exception
} 

答案 2 :(得分:3)

你不能调用普通删除,因为它会尝试释放没有用普通new分配的内存,所以你直接调用析构函数然后根据你使用的体系结构处理底层内存分配。

答案 3 :(得分:3)

通常,使用new创建对象,并在对象上调用delete时销毁。但是,因为'delete'也会尝试将底层内存释放回堆中,所以不应该在使用placement delete实例化的对象上调用new

然而,(无论如何分配)每个对象都应该被销毁(因为它的析构函数可能会做一些重要的事情)。

因此,使用delete而不是使用{{1}}销毁对象,您必须自己销毁对象,并通过调用其析构函数明确地执行此操作,如您引用的常见问题解答所示。

答案 4 :(得分:2)

您链接中的示例:

void someCode()
 {
   char memory[sizeof(Fred)];
   void* p = memory;
   Fred* f = new(p) Fred();
   ...
   f->~Fred();   // Explicitly call the destructor for the placed object
 } 

“placement new”返回我们提供的内存偏移量。在 new 之后,编译器会向ctor添加一个调用(“placement new”也是一个明确调用ctor的技巧)。

“内存”在堆栈中分配,因此我们无法删除它。

答案 5 :(得分:0)

string *ps = new string("Hello ");

上述声明中的新内容称为 new operato r,它做了两件事

  1. 调用operator new(分配 必要的记忆,如malloc)和
  2. 调用构造函数 在运营商创建的原始内存上 新手初始化

    删除ps;

  3. 再次删除对应

    1. 破坏对象和
    2. 释放内存(即免费)
    3. 在c ++中,不允许用户直接调用构造函数,当你通过某种方式分配原始内存并想用构造函数初始化这些位时,会使用Placement new。因为内存分配过程没有通过operator new发生,所以删除不能释放记忆。

      void someCode()
           {
             char memory[sizeof(Fred)];//memory allocated on stack
             void* p = memory;
             Fred* f = new(p) Fred();//placement new 
             ...
             f->~Fred();   // Explicitly call the destructor for the placed object
           }