是否可以在分配了新位置的指针上删除调用?

Nar*_*rek 5 c++ memory-management placement-new new-operator

我们可以调用delete分配了位置new的指针吗?如果没有那么为什么?请详细说明.

我知道没有放置删除.但我想知道为什么只删除opetator无法删除内存而不关心如何分配指针指向的内存?

delete 正在做两件事:

  1. 叫destrucor
  2. 释放记忆

我认为没有删除的原因是不能在由placement new创建的对象上调用这两个操作中的任何一个.对原因有什么想法吗?

Set*_*gie 7

您只能调用delete使用创建的指针operator new.如果您使用new具有由法线分配的内存位置的放置,operator new那么您可以安全地使用delete它(前提是您获得正确的类型和指针).但是,您可以new在任何内存上使用放置,因此您通常会以其他方式管理该内存并手动调用该对象的析构函数.

例如,在这种复杂且通常不必要的情况下,对于delete您使用放置的内存是安全的new,但仅仅因为您new之前分配了它:

char* mem = new char[sizeof(MyObject)];
MyObject* o = new (mem) MyObject;

// use o

o->~MyObject(); // with placement new you have to call the destructor by yourself

delete[] mem;
Run Code Online (Sandbox Code Playgroud)

但是,这是非法的:

char mem[16]; // create a buffer on the stack, assume sizeof(MyObject) == 16

MyObject* o = new (mem) MyObject; // use stack memory to hold a MyObject
                                  // note that after placement new is done, o == mem
                                  // pretend for this example that the point brought up by Martin in the comments didn't matter

delete o; // you just deleted memory in the stack! This is very bad
Run Code Online (Sandbox Code Playgroud)

另一种思考方式是delete 释放先前由法线分配的内存new.使用放置new,您不必使用由正常分配的内存new,因此可能无法正常分配new,delete无法处理它.


Ant*_*tti 5

不,因为删除不仅会调用析构函数,还会释放内存,但如果使用了placement new,则必须使用malloc()或stack自己分配内存.但是,您必须自己调用析构函数.另请参阅C++ FAQ.


Rem*_*anu 5

EDIT1:我知道没有放置删除。但是我想知道为什么只删除操作符不能删除内存而不关心指针指向的内存是如何分配的?

因为每种类型的内存分配都使用一些特定于实现的内存跟踪(通常是用户地址之前的头块),这使得分配/释放只有在正确配对时才能工作:

  • new 必须配对 delete
  • new[]必须配对delete[](大多数实现虽然原谅混合newnew[]
  • malloc 和炸薯条必须搭配 free
  • CoTaskMemAllocCoTaskMemFree
  • alloca 没有任何配对(堆栈展开处理它)
  • MyCustomAllocatorMyCustomFree

尝试调用错误的解除分配器将导致不可预测的行为(现在或以后很可能是段错误)。因此,调用delete由其他任何东西分配的内存new会导致不好的事情。

此外,放置 new 可以在任何地址上调用,甚至可能不是已分配的地址。它可以在位于某个较大对象中间的地址上调用,可以在内存映射区域上调用,也可以在原始虚拟提交区域上调用,任何事情都可以。delete在所有这些情况下,将尝试执行其实现告诉他要做的事情:减去标头大小,将其解释为new标头,将其链接回堆。卡布姆。

知道如何释放新地址的内存的是,因为你确切地知道内存是如何分配的。delete只会做它知道的事情,这可能不是正确的事情。