为什么在C ++中没有放置删除表达式?

时间:2011-05-02 12:42:02

标签: c++ c++11 new-operator delete-operator

为什么C ++没有直接对应于placement new的展示位置删除,即调用析构函数并调用相应的展示位置删除运算符?

例如:

MyType *p = new(arena) MyType;
...
//current technique
p->~MyType();
operator delete(p, arena);

//proposed technique
delete(arena) p;

5 个答案:

答案 0 :(得分:22)

operator delete在作为动态分派的非成员或静态成员函数时是唯一的。具有虚析构函数的类型从最派生的析构函数执行对其自己的delete的调用。

struct abc {
    virtual ~abc() = 0;
};

struct d : abc {
    operator delete() { std::cout << "goodbye\n"; }
};

int main() {
    abc *p = new d;
    delete p;
}

Run this example。)

为了使用放置删除,析构函数必须以某种方式将其他参数传递给operator delete

  • 解决方案1:通过虚函数传递参数。这需要为每个静态成员和具有不同参数的全局operator delete重载使用单独的虚拟析构函数。
  • 解决方案2:让虚拟析构函数返回一个指向调用者的函数指针,指定应调用的operator delete。但是如果析构函数执行查找,则会遇到需要多个虚函数定义为#1的相同问题。必须创建某种抽象的重载集,调用者才能解析它。

你有一个非常好的观点,它将是一种很好的语言补充。理论上,将其改编为delete的现有语义甚至可能是可能的。但是大多数时候我们不使用delete的全部功能,只需使用伪析构函数调用,然后使用类似arena.release(p)的内容。

答案 1 :(得分:21)

因为我们已经有ptr->~type();

,所以没有必要

答案 2 :(得分:8)

可能是因为有没有解除分配显式调用析构函数的语法(与你的问题完全相同),但原始内存中没有显式构造的语法?

答案 3 :(得分:7)

实际上有一个放置删除,如果构造函数抛出异常,则使用placement new“分配”的对象的实现调用。

From Wikipedia

  

从展示位置新表达式调用展示位置删除功能。特别是,如果对象的构造函数抛出异常,则调用它们。在这种情况下,为了确保程序不会导致内存泄漏,调用放置删除功能。

答案 4 :(得分:2)

新的放置点是将对象创建与内存管理分开。所以在对象破坏期间将它绑回来是没有意义的 如果对象的内存来自堆,并且您希望对象及其内存具有相同的生命周期,请使用operator newoperator delete,如果您想要任何特殊行为,可能会覆盖它们。
例如,vector中的Placement是很好的,它可以保留大量的原始内存,并在其中创建和销毁对象,但不释放内存。