0

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

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

    object->T::~T (); 

    ::new (object) T; 

    return object; 

 }

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

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

4

3 回答 3

2

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

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

于 2014-02-12T06:30:28.973 回答
1

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

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

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

正如其他提到的:

  • 没有空检查。
  • 不考虑异常安全
于 2014-02-12T10:10:24.153 回答
1

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

于 2014-02-12T05:56:41.770 回答