在一个类的析构函数中,NULL 是什么意思?

3

可能是重复问题:
在析构函数中将指针设置为NULL的作用是什么?

在析构函数中将分配堆内存的指针设置为NULL是没有意义的吗?

class SampleClass
{
    public:
        SampleClass( int Init = 0 )
        {
            Value = new int( Init );
        }

        ~SampleClass( void )
        {
            delete Value;
            Value = NULL; // Is this pointless?
        }

        int *Value;
};

谈到类时,何时应该使用explicit关键字?


完全复制 在析构函数中将指针设置为NULL值是否值得?。我完全同意Michael Burr的回答,他用粗体字说:“不要这样做。” - James McNellis
explicit 的用法在 "What does the explicit keyword in C++ mean?" 中有解释。 - James McNellis
谢谢你的链接,詹姆斯 :) - DeadCapacitor
4个回答

5

是的。这是没有意义的,因为对象正在被销毁处理中。 一旦对象被销毁,就没有办法访问指针了。


但是对象的内存并没有被清除。如果您有另一个指向SampleClass对象实例的指针(这可能会发生-出于错误),则可以访问该内存。 - Matěj Zábský
3
如果你遇到这个问题,最好使用一个更智能的指针,以避免对象被过早地删除。试图防止程序中其他错误是相当无意义的。 - Bo Persson

4

是的,在析构函数最后将指针设置为NULL没有意义,因为一旦离开析构函数,它将不再存在。

当您希望避免隐式转换为您的类类型时,可以使用explicit关键字。 :-)

例如,如果MyClass有一个接受int的构造函数和一个f(const MyClass&)函数,则可以将f调用为:

f(42)

或者

f(MyClass(42))

如果你将构造函数设为显式,只有后者才能起作用。这可以避免一些不必要的隐式转换。

1

这并不是毫无意义的。虽然从理论上讲,该值永远无法再次访问,但将其设置为NULL可能会在未来帮助您应对其他问题。


1
虽然如果它有帮助的话,它几乎肯定不会像将其设置为一些引人注目的值那样有帮助。 - Steve Jessop
不,NULL特别意味着我手动设置了它。这不一样。 - Puppy
2
0xDEADBEEF 做的事情是相同的,但它还传达了额外的含义:“我设置了这个值,希望不会再看到它”。 - MSalters

0

把指针设置为NULL是更好的选择。

如果您在代码的其他地方删除了SampleClass实例,然后访问Value(使用另一个指向同一实例的指针),您将知道出了问题,因为程序会崩溃于NULL解引用(从而表明您正在访问已删除的对象)。

否则,您可能会继续使用已删除的对象,并且只有在很久以后(当内存被另一个对象覆盖时)才注意到错误。这些问题通常极难调试。


3
同样的道理,建议不要将指针设为NULL。如果在同一指针上再次调用delete,它会忽略这个请求并且你可能不会意识到代码中隐藏的错误。请注意,此时代码仍在运行。 - David Rodríguez - dribeas
@David Rodríguez - dribeas,规则是尽早揭示错误 = 在取消空值引用时使程序崩溃。 - Matěj Zábský
@David Rodríguez,你最好使用断言或异常来处理这个问题。 - whyleee
3
这是错误的:取消引用指向已不存在的对象的指针只是可能在此情况下发生的一种错误。例如,如果您在析构函数中delete p; p = NULL;,然后稍后检查if (p == NULL),代码仍然是错误的,现在您的检查已经导致您无法找到此错误。你正在以发现某些其他类型的错误的能力来交换发现一种错误的能力。 - James McNellis
3
不将指针设置为NULL的好处在于,良好的调试运行时(例如Visual C++调试堆提供的运行时)会使用可识别的模式填充已释放内存的内容,因此当程序崩溃时很容易发现错误。这有效地使您能够更轻松地捕获大多数此类错误,远远超过如果您将p = NULL;。Michael Burr在链接的重复问题中更优雅地解释了这一点。 - James McNellis

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