2013-07-15 30 views
0

我想定义我自己的放置新的和放置删除(带额外的参数),我发现我可以正确调用放置,而我无法访问放置删除。任何人都可以告诉我是否我错误地定义了位置删除或者我错误地调用了它?C++自定义的放置新的和放置删除调用

class A 
{ 
public: 
    A(int a) : a(a){} 

    static void* operator new(std::size_t, int); // the placement new 
    static void operator delete(void*, int)throw(); // the corresponding placement delete 
private: 
    int a; 
}; 

void* A::operator new(std::size_t size, int n) 
{ 
    std::cout << "size: " << size << " " << "n: " << n << std::endl; 
    return ::operator new(size); 
} 

void A::operator delete(void* p, int n)throw() 
{ 
    std::cout << "n: " << n << std::endl; 
    ::operator delete(p); 
} 

int main(int argc, char* argv[]) 
{ 
    A* a = new(10) A(100); 

    std::cout << std::endl; 

    delete(4) a; // error???????????????????, but how? 

    return 0; 
} 
+0

[为什么在C++中没有放置删除表达式?](http://stackoverflow.com/questions/5857240/why-there-is-no-placement-delete-expression-in-c) – Suma

+0

这看起来不像新的位置,特别是你实例化你的'A *'指针的方式(不确定10是否是正确的内存位置:P)。看看这里:http://www.parashift.com/c++-faq/placement-new.html – Xaqq

+1

@Xaqq:它是一种新的布局形式,但不是最常见的一种,它通过地址该对象将被放置。 –

回答

3

放置delete仅提供给处理放置new表达的评估,在此期间发生的异常。如果施工成功完成,则将在正常的delete后面使用。

您可以明确调用展示位置释放函数,但它不会与delete运算符具有相同的行为(它不会自动调用析构函数)。

在你的情况,相应的代码如下:

a->~A(); 
A::operator delete(a, 4); 

呸!

对于数组来说更糟的是,因为您无法从编译器存储的位置检索元素的数量(以及调用的析构函数的数量)以供自己使用。

设计您的超载operator new,以便它与单参数operator delete正确配对。那么你的类的用户可以使用delete ptr;std::unique_ptr

如果你确实需要定制释放,然后用定制删除返回std::shared_ptr分配的包装会比自定义布局新的更好的。

+0

这是否意味着我无法更改放置删除的签名,我只能重新定义它?当我想释放资源时,我打电话:a->〜A();删除一个; ? – JavaBeta

+1

@JavaBeta:编号'delete a;'会第二次调用析构函数,然后是单参数释放函数'operator delete(void *)'。如果你想调用一个不同的(放置)释放函数,就像我的答案显示的那样明确地执行。如果你可以让普通的释放函数正常工作,那么你的类的用户可以说'delete p;'并且同时得到析构函数调用和释放。 –

+0

哦,我必须通过范围操作符明确调用它?它的工作,它仍然让我困惑,无论如何,放置新的和放置删除调用机制是非常不一致的。 – JavaBeta