C++:在调用“delete”之前将类中的指针赋值为NULL

3
在删除前,是否有必要将类中的所有指针赋值为NULL?我的意思是,例如以下二叉搜索树节点删除函数的代码片段: 1.
Node *temp = parent->left;
parent->left = temp->left;
delete temp;

2.

Node *temp = parent->left;
parent->left = temp->left;
temp->left = NULL;
delete temp;

这条线是指

temp->left = NULL;

必要的吗?一些教程会这样做,而另一些则不会。

只有在存在其他代码可能会访问已被释放但非空的指针时,才必须这样做。 - Paul Beckingham
这要看你的节点析构函数是否会对指针进行任何操作,如果你不删除它,比如递归清理一个你可能想保留的节点,那么就要考虑一下了。 - Rup
不,析构函数是默认的。 - Kudayar Pirimbaev
2
你应该只使用现代C++风格,不必担心它。相关:零规则 - Griwes
+1 非常现代化的 C++ 风格,源代码非常全面。 - Kudayar Pirimbaev
5个回答

4

这可能是不必要的。在删除temp后,没有代码可以安全地解引用它。但是如Ralph Tandetzky所指出的那样,如果Node具有对其left成员进行操作的析构函数,则是有效的。

将其成员设置为NULL的另一个可能的好处是更可预测地捕获无效访问。


4
取决于情况。如果Node的析构函数删除了子节点,那么这行代码是必要的。如果没有删除,那么这行代码就不是必要的。然而,一些教程可能会将其包括进来,仅仅是为了推广良好的编程风格。如果你在程序中引入了一个错误,并在删除后继续使用指针,则具有空指针将给你一个错误消息,而不是未定义的行为。如果你想更严格地遵循这种风格,你也可以添加temp = NULL;这行代码。

1
+1。我(以及迄今为止的所有其他答案)都忽略了这种可能性。 - simonc
1
删除 temp 后,访问 temp->left 是未定义的,即使在删除 temp 之前设置 temp->left = NULL 也无法避免这种情况。 - Daniel Daranas
1
你能否举例说明它为什么可能是必要的? - juanchopanza
@juanchopanza:微不足道。Node::~Node() { delete this->left; }。当然不是一个好主意(存在堆栈溢出的风险),但从技术上讲是合法且无泄漏的。使用这种方式,删除头节点将删除整个列表。 - MSalters
@MSalters 我不太确定UB是什么意思,但在删除指针后将其设置为null可能是有意义的。这就是为什么std::unique_ptrstd::shared_ptr在重置时被设置为null的原因之一。它们不仅会删除,还会设置为零。通常在发布模式下不会花费你任何代价,因为将指针设置为null很容易被任何现代编译器优化掉。 - Ralph Tandetzky
显示剩余3条评论

1
这并非必须,而是一种旨在帮助调试的措施。想象一下,如果你没有使用NULL(例如,在链表中),并且不知怎么地进入了已被释放但其内容尚未删除的内存,则可能存在跟随该指针的危险,而实际上并不知道它是否仍然存在,甚至可能在已经删除该内存时尝试删除该内存。
因此,这只是为了安全考虑,而不是为了实现任何功能。还有另一种(互补的)方法来实现相同的效果:检测所访问的内存是否已被删除。例如:
class Node {
public:
    Node()
        { status = 0xf00dbeef; }
    ~Node()
        { status = 0xdeadbeef; }
    // ...
private:
    int status;

    bool isAlive() const
        { return ( status == 0xfoodbeef ); }
};

这样,您可以始终确保使用正确分配的内存,即它a)未被释放并且b)实际上存储了一个Node对象。希望这有所帮助。

1
不需要这样做,但如果left指针所指的内存是对象拥有的,则应相应地进行删除

危险的注释:在C++中,您不应该调用free(node->left)。在最坏的情况下,您应该使用deletemalloc/free是C风格。现代C++风格使用智能指针,或者只需使用std::list<> - MSalters

1

不需要这行代码:

temp->left = NULL;

在许多情况下,如果你强制自己在每次删除后添加此行代码,它可能很有帮助,因为如果程序崩溃并且你看到指针被设置为零,你就可以轻松地识别错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接