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

30 c++ new-operator delete-operator c++11

为什么C++没有直接对应于贴图新的贴片删除,即调用析构函数并调用适当的贴片删除操作符?

例如:

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

//proposed technique
delete(arena) p;
Run Code Online (Sandbox Code Playgroud)

Pot*_*ter 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 Code Online (Sandbox Code Playgroud)

(运行此示例.)

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

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

你有一个非常好的观点,它将成为语言的一个很好的补充.delete理论上,甚至可能将其改造成现有的语义.但是大多数时候我们不使用完整的功能,delete只需使用伪析构函数调用就可以了arena.release(p).


use*_*016 20

因为我们已经拥有,所以没有必要 ptr->~type();

  • @Richard:好的,*正是*.就像放置新的调用构造函数但不分配内存一样. (40认同)
  • 这是不一样的.当您调用placement new时,您将获得2个函数调用.一个到适当的"operator new",另一个到构造函数.当你调用`ptr-> ~type()`时,你只能调用析构函数.没有相应的调用释放功能.也许你可以增强你的答案,以便你解释我们可以追踪"ptr"的内存现在可以重复使用的地方. (15认同)
  • -1:这会调用析构函数但不释放内存. (9认同)
  • -1 ...同意@RichardCorden.您还可以说"我们不需要用户定义的放置操作符新表单,我们可以使用标准提供的放置操作符新表单手动调用构造函数.在哪里获取内存从*向上*到您*".这似乎是一个有缺陷的论点. (7认同)
  • @Richard:哦,是的,我确实倒退了.但是我再说一遍:我们确实*不需要删除位置,因为我们已经可以使用`p-> ~type()`来破坏一个新的放置对象.你对剩下的记忆是什么*取决于你*.重用或免费. (6认同)
  • @Circada:你能详细说说吗?OP问他为什么需要调用`p-> ~type()`来销毁对象 - 和`operator delete(p,arena)`来处理内存.你回答,只是破坏对象,内存将由?????处理 你确定这是误解了这个问题吗? (5认同)
  • @RichardCorden如果不是我,有人会最终向你扔石头.新安置不会执行内存分配.见[here and read#5](http://en.cppreference.com/w/cpp/memory/new/operator_new) (4认同)
  • @Richard:我认为你误解了这个问题. (3认同)

Nik*_*sov 8

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

  • 原始内存中的显式构造正是新的布局.(记忆也可以从"竞技场"对象中获得.)但是这个答案并没有在构造和破坏之间产生任何实际联系; 关键不明确. (4认同)

Mot*_*tti 7

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

来自维基百科.

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