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

时间:2010-11-21 06:32:47

标签: c++

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

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

private: 
  std::vector < double > values_;
};

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

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

private: 
  A * p_;
};

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

3 个答案:

答案 0 :(得分:11)

在类A中,绝对没有理由在析构函数中.clear() vector - 类型的成员变量。调用vector析构函数时.clear()vector {/ 1}}。

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

delete p_;

无需先测试p_ != NULL是否因为delete NULL;被定义为无操作。在p_ = NULL之后也无需设置delete,因为p_在其成员的对象被销毁后无法再合法访问。

那就是说,你应该很少需要在C ++代码中使用delete。您应该更喜欢使用范围限制资源管理(SBRM,也称为资源获取是初始化)来自动管理资源生命周期。

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

答案 1 :(得分:2)

在你的第二个例子中,没有理由将p_设置为null,特别是因为它是在析构函数中完成的,这意味着p_的生命周期将在此之后立即结束。

此外,在调用p_之前将delete与null进行比较没有意义,因为delete表达式在内部执行此检查。在您的特定人工示例中,析构函数应该只包含delete p_并注明其他内容。没有if,没有设置p_为空。

答案 2 :(得分:0)

在p_的情况下,不需要在析构函数中将其设置为null,但它可以是一种有用的防御机制。想象一下,如果你有一个bug,那么在删除B对象后仍然会有一个指向B对象的指针:

如果它试图删除B对象,则p_为null将导致第二次删除无害而不是堆腐败。

如果它试图在B对象上调用方法,则p_为null将立即导致崩溃。如果p_仍然是旧值,则结果未定义,并且可能难以追踪导致崩溃的原因。