为什么人们想要明确地清除一个向量成员变量(在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_无效呢?
答案 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_ptr
和std::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_仍然是旧值,则结果未定义,并且可能难以追踪导致崩溃的原因。