【问题标题】:Correct usage of placement-new and explicit destructor call正确使用placement-new和显式析构函数调用
【发布时间】:2014-03-10 07:01:33
【问题描述】:

在最近的一次采访中,我被要求回答这段代码是否安全以及我何时会使用这样的代码:

template<class T> T *CTricky<T>::Safe_Or_Not (T *object) 
{ 

    object->T::~T (); 

    ::new (object) T; 

    return object; 

 }

我的回答是:这段代码是安全的,如果我需要通过调用它的析构函数来释放我的“对象”使用的资源,我会使用这种技术,但同时我不想释放我的“对象” " 并希望它保留在内存中的位置(通过在此处放置 new 来实现)。

老实说,我并不是在寻求帮助来在面试中正确回答这个问题。我只是好奇我对放置 new 和显式析构函数调用的理解是否正确。

【问题讨论】:

  • 这就是为什么要为对象回收空间(以及其他一切!),移动语义非常棒。

标签: c++ placement-new explicit-destructor-call


【解决方案1】:

简短的回答:虽然它不一定会导致问题,但要真正安全地做到这一点是相当困难的。最大的问题是,如果通过放置 new throws 调用的构造函数,您已经销毁了该对象,但是堆栈展开会再次尝试销毁它,从而导致未定义的行为。

虽然还有一些其他的事情需要注意(例如,空指针),但这可能是最不明显和最难防止它引起问题的事情(基本上,你唯一的选择就是忍受未定义的行为并希望最好,或者在堆栈展开之前捕获异常并退出程序)。

【讨论】:

    【解决方案2】:

    这是安全的: 以下可能会产生内存泄漏:(https://ideone.com/70YqhM)

    Base* b = new Derived;
    b = Safe_Or_Not(b);
    

    派生的析构函数永远不会被调用。

    另外提到:

    • 没有空检查。
    • 不考虑异常安全

    【讨论】:

      【解决方案3】:

      我认为一般的“显式析构函数调用 + 放置新”逻辑是安全的。
      但是,这段代码并不安全,因为:
      - 您不检查指针是否为空。 - 不考虑异常安全

      【讨论】:

        猜你喜欢
        • 2018-06-06
        • 2021-08-31
        • 2023-03-22
        • 1970-01-01
        • 1970-01-01
        • 2021-01-28
        • 2018-04-05
        相关资源
        最近更新 更多