我是否需要在析构函数中使成员变量无效?

Mic*_*ael 6 c++

为什么人们想要明确地清除一个向量成员变量(在dtor中为on)(请参见下面的代码).清除向量有什么好处,即使它会在dtor代码的最后一行之后被销毁被执行?

class A
{
~A()
{
   values.clear();
}

private: 
  std::vector < double > values_;
};
Run Code Online (Sandbox Code Playgroud)

关于以下代码的类似问题:

class B
{
~B()
{
   if (NULL != p)
   {
       delete p_;
       p_ = NULL;
   }
}

private: 
  A * p_;
};
Run Code Online (Sandbox Code Playgroud)

由于dtor无法被调用两次,为什么要取消p_呢?

Jam*_*lis 11

在类中A,绝对没有理由在析构函数中.clear()使用vector-type成员变量.该vector析构函数将.clear()vector被调用时.

在类中B,清理代码可以简单地写成:

delete p_;
Run Code Online (Sandbox Code Playgroud)

没有必要先测试是否p_ != NULL因为delete NULL;被定义为无操作.p_ = NULL在你删除之后也没有必要设置delete它,因为p_在它成为成员的对象被销毁之后再也无法合法访问.

也就是说,您应该很少需要delete在C++代码中使用.你应该更喜欢使用范围,结合资源管理(SBRM,也被称为资源获取就是初始化)来自动管理资源的寿命.

在这种情况下,您可以使用智能指针. boost::scoped_ptrstd::unique_ptr(来自C++ 0x)都是不错的选择.与使用原始指针相比,它们都没有任何开销.此外,他们都禁止生成隐式声明的拷贝构造函数和拷贝赋值运算符,通常是你想要的东西,当你有一个成员变量是一个指向一个动态分配的对象.

  • @edA:不,不是真的.它应该很少使用.给我们一个您认为需要它的情况,我们会让它更清洁,更安全.**应该包装所有**资源,因此您只需使用包装器.如果除了析构函数之外你还有一个`delete`,那你就错了 (5认同)
  • @edA:我支持这一说法.在过去的两年里,我没有在新的生产代码中编写一个`delete`表达式(在编写正确的C++代码之前,我是一个完整的noob). (5认同)
  • 除了"很少使用C++中的删除"代码之外,答案很好.我同意像auto_ptr和unique_ptr这样的事情可以解决许多情况,但是说"删除"应该/很少/使用是完全错误的. (4认同)
  • @Crashworks:请注意,在我的回答中,我没有说"你永远不需要使用`delete`;" 我说"你应该**很少**需要使用`delete`." 我故意选择**很少**这个词.很少需要编写自己的资源拥有容器(通常,您可以通过组合更原始的容器来实现自己的容器).在"所有C++代码"的类别中,为设备驱动程序编写的代码远远少于为更高级别的库,应用程序和其他类似的东西编写的代码(也就是说,我认为驱动程序代码也很少见) . (4认同)
  • @eda:用户应该*从不*调用`delete`,因为面对异常,这是资源泄漏的一个秘诀.RAII是C++不可或缺的一部分,与手动删除相比,**不会花费任何成本**,但它更安全.RAII的隐式清理是一件好事*,用户不应该手动操作(因为他们*迟早会弄错). (2认同)