【问题标题】:If I write a placement new?How should I write normal operator delete?如果我写一个placement new?我应该如何写正常的operator delete?
【发布时间】:2016-04-22 01:07:35
【问题描述】:

在“Effective C++”第 52 条:如果你写placement new,写placement delete。

Meyers 说对于Widget *pw = new (std::cerr) Widget;,将调用placement new。但是如果放置 new 没有抛出异常,我们会在客户端代码中删除:delete pw;。然后,这个delete 只会调用普通删除,而不是放置删除。

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

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

【问题讨论】:

  • 一开始你不应该这样做,但如果你这样做了,就让自定义的operator delete 调用普通的。注意:如果您不提供带有与operator new 对应的参数的operator delete,则代码可以编译但行为异常(内存泄漏)。
  • 你的意思是我不应该这样做:“正常的运算符删除应该类似于放置删除”?@Cheersandhth.-Alf
  • 不明白你的意思,抱歉。
  • 我的意思是你认为我一开始就不应该做的事情。你能详细说一下吗?@Cheersandhth.-Alf
  • 哦。你不应该做低级分配器的事情。

标签: c++ new-operator delete-operator placement-new


【解决方案1】:

类似这样的:

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'; 
    }
}

【讨论】:

  • 但是我觉得这不是Meyers想要做的。他不想用try catch。如果我用Widget* p1 = new Widget;怎么办我想知道正常的operator delete会是什么样子在这种情况下@Andreas DM
  • 首先,放置new和delete会隐藏全局运算符new和delete,这可能会导致错误。我确定。其次,我想知道普通运算符删除的实现,但是安德烈亚斯没有提供。这些是我这么说的两个原因。@TonyD
【解决方案2】:

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

相反,当你想删除一个由placement new创建的对象时,你必须通过Widget::delete(pw, std::cerr)调用placement delete。你不应该直接调用delete pw,如果你这样做,编译器会报错。在vs2013中,编译器会输出

不能删除指向该类型对象的指针;该类没有“运算符删除”的非放置重载

因此,在普通操作符删除中无需担心放置删除。

【讨论】:

    猜你喜欢
    • 2018-01-14
    • 2017-03-21
    • 2021-08-31
    • 2011-11-03
    • 2010-11-06
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    相关资源
    最近更新 更多