正确使用placement-new和explicit析构函数调用

时间:2014-02-12 05:48:18

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

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

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

    object->T::~T (); 

    ::new (object) T; 

    return object; 

 }

我的回答是:这段代码是安全的,如果我需要通过调用它的析构函数释放我的“对象”所使用的资源,我会使用这种技术,但同时我不想释放我的“对象” “并希望它能够将它放在记忆中(通过在这里放置新的东西来实现)。

老实说,我没有寻求帮助,在面试时正确回答了这个问题。我只是想知道我对放置新的和显式的析构函数调用的理解是否正确。

3 个答案:

答案 0 :(得分:2)

简短回答:虽然它不一定会导致问题,但这样做非常安全非常困难。最大的问题是,如果构造函数通过放置新的throws调用,你已经销毁了对象,但是堆栈展开将尝试再次销毁它,导致未定义的行为。

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

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

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

另如提及:

  • 没有空检查。
  • 不考虑例外安全