如果我写一个新的展示位置?我应该如何编写普通运算符删除

If I write a placement new?How should I write normal operator delete?

本文关键字:我应该 位置 何编写 删除 运算符 一个 如果      更新时间:2023-10-16

在"有效C++"中 第 52 项:写放置 如果写新放置,请删除。

迈耶斯说,对于Widget *pw = new (std::cerr) Widget;,将调用放置新位置。但是,如果放置 new 没有抛出异常,并且我们会在客户端代码中删除:delete pw; .然后,此delete将仅调用正常删除,而不调用放置删除。

然后,Meyers 得出的结论是,您必须提供正常的运算符删除。那么,这个普通的运算符删除应该是什么样的呢?我认为这个普通运算符删除的内部应该类似于放置删除。

但是如果我使用普通运算符 new 而不是放置 new 来创建对象Widget *pw = new Widget;,然后使用delete pw,那么它也会调用我为放置编写的普通运算符 delete new 。但这似乎不对。

像这样:

struct Widget {
    Widget() { throw std::runtime_error(""); }
    // custom placement new
    static void* operator new(std::size_t sz, const std::string& msg) {
        std::cout << "custom placement new called, msg = " << msg << 'n';
        return ::operator new(sz);
    }
    // custom placement delete
    static void operator delete(void* ptr, const std::string& msg)
    {
        std::cout << "custom placement delete called, msg = " << msg << 'n';
        ::operator delete(ptr);
    }
};
int main() 
{
    try {
        Widget* p1 = new ("widget") Widget;
    } 
    catch(const std::exception& e) {
        std::cout << e.what() << 'n'; 
    }
}

您不需要编写类似于放置删除的普通运算符删除。

相反,当您要删除由放置 new 创建的对象时,您必须通过 Widget::delete(pw, std::cerr) 调用放置删除。你不应该直接调用delete pw,如果你这样做,编译器会抱怨。在 vs2013 中,编译器将输出

无法删除指向此类型对象的指针;该类没有用于"运算符删除"的非放置重载

因此,无需担心在正常运算符删除中的位置删除。