关于删除通过放置新创建的对象的困惑
Confusion about deleting objects created via placement new
我不完全确定下面的代码中发生了什么:
#include <iostream>
struct Foo
{
double dummy{42};
static void* operator new(std::size_t size, void* p)
{
std::cout << R"(Calling placement "operator new" for size )"
<< size << 'n';
return ::operator new(size, p);
}
Foo()
{
std::cout << "Foo::Foo()" << std::endl;
}
~Foo()
{
std::cout << "~Foo::Foo()" << std::endl;
}
};
int main()
{
void* buf_heap = new char[128] {};
Foo* pFoo_heap = new(buf_heap) Foo; // placement allocation
// why does this line call the correct operator delete?
delete pFoo_heap;
// the line above seems to be equivalent to:
// pFoo_heap->~Foo();
// ::operator delete(buf_heap);
}
我知道,每当在构造对象时使用放置new
时,都应该手动调用析构函数,然后调用以释放内存(通常通过::operator delete
、::operator delete[]
或free
,具体取决于放置new
的实现方式),请参见例如如何删除通过放置新运算符构造的对象?
然而,在上面的代码中,我创建了一个Foo
对象,并将其放置在堆分配的内存中。然后,当我调用delete pFoo_heap
时,析构函数会被自动调用(我理解这一点),但内存似乎也会被释放(在这种情况下是buf_heap
)。也就是说,如果我尝试之后做::operator delete[](buf_heap);
,我会得到一个segfault。
所以基本上线
delete pFoo_heap;
似乎相当于
pFoo_heap->~Foo();
::operator delete[](buf_heap);
事实确实如此吗(或者只是UB)?为什么buf_heap
中分配的内存被取消分配?或者,换句话说,即使通过放置new
分配,delete pFoo_heap;
是否知道内存来自哪里?
您问:
// why does this line call the correct operator delete?
delete pFoo_heap;
// the line above seems to be equivalent to:
// pFoo_heap->~Foo();
// ::operator delete(buf_heap);
这不是真的。您的代码受到未定义行为的影响。来自C++标准:
5.3.5删除
2如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并在本节剩余部分使用转换后的操作数代替原始操作数。在第一种选择(删除对象)中,
delete
的操作数的值可以是空指针值、指向由以前的新表达式创建的非数组对象的指针,或者指向表示此类对象基类的子对象(1.8)的指针(第10条)。如果不是,则行为未定义。
在您的案例中,pFoo_heap
不是由新表达式创建的,buf_heap
是由new表达式创建的。您需要使用:
pFoo_heap->~Foo();
delete [] buf_heap;
对于一个表现良好的程序。
为什么
buf_heap
中分配的内存被取消分配?
因为您正在取消分配它。请注意,buf_heap == pFoo_heap
,所以当您执行delete pFoo_heap
时,它恰好与您开始执行new Foo
时一样工作-您正在删除的指针指向以前使用new
分配的内存。所以它…"有效"。。。
- 使用基类指针创建对象时,缺少派生类析构函数
- 如何创建对象函数指针C++映射?
- C++创建对象数组
- 在 C++ 的 Switch Case 中创建对象后对对象调用方法
- 如何获取在 main() 函数中构造的类的创建对象?
- 基于文件中的条目创建对象
- 错误:创建对象后无法分配区域
- C++ 通过输入创建对象
- 堆还是堆栈用于创建对象?
- 使用 C++ 创建对象数组
- 使用unique_ptr创建对象
- C++递归地在类构造函数中创建对象
- 通过向构造函数其他对象引用页面来创建对象
- ReactiveX (rx) - 在对象上应用可观察对象,而不是在可观察对象中创建对象
- 如何在OSX上正确创建C++对象文件(.o)
- 编译器是否会创建vtable,而不考虑在c++中创建对象
- 创建对象并防止被破坏
- 在C++中,友元类可以从友元类创建对象吗
- 只在堆中创建C++对象
- 创建用户定义的复制构造函数时无法创建对象