关于删除通过放置新创建的对象的困惑

时间:2015-04-17 21:17:02

标签: c++ memory-management 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的展示位置),请参阅例如How to delete object constructed via placement new operator?

但是,在上面的代码中,我创建了一个Foo对象,我将其放在堆分配的内存中。然后,当我调用delete pFoo_heap时,会自动调用析构函数(我理解这一点),但似乎内存也被释放(在这种情况下为buf_heap)。也就是说,如果我尝试::operator delete[](buf_heap);我会遇到段错误。

基本上就是

delete pFoo_heap;

似乎等同于

pFoo_heap->~Foo(); 
::operator delete[](buf_heap);

确实如此(或者只是UB)?为什么在buf_heap中分配的内存被解除分配?或者换句话说,即使通过展示位置delete pFoo_heap;分配,new也知道内存的来源吗?

2 个答案:

答案 0 :(得分:3)

你问:

// 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的操作数的值可以是空指针值,指向由前一个 new创建的非数组对象的指针-expression ,或指向表示此类对象的基类的子对象(1.8)的指针(第10条)。如果不是,则行为未定义。

在您的情况下,pFoo_heap不是由 new-expression 创建的,buf_heap是由 new-expression 创建的。你需要使用:

pFoo_heap->~Foo();
delete [] buf_heap;

表现良好的节目。

答案 1 :(得分:1)

  

为什么在buf_heap中分配的内存被解除分配?

因为你要取消分配它。请注意buf_heap == pFoo_heap,因此当您执行的delete pFoo_heap恰好就像您开始使用new Foo时一样 - 您要删除的指针指向之前已分配的内存与new。所以它......“有效”......