临时将指针设为 NULL 有什么意义吗?

Is there any point to temporarily making a pointer NULL?

本文关键字:什么 NULL 指针      更新时间:2023-10-16

我见过很多这样的代码:

SomeType* ptr = NULL;
ptr = SomeMethod(some, params);

有什么意义?我也看到过它在其他地方声明ptr(例如在类定义中),然后在类构造函数中会有这个:

ptr = NULL;
ptr = SomeMethod(some, params);

我不明白为什么要这样做。ptr = NULL线肯定没用吗?

如果"SomeMethod"抛出异常,你的SomeType*将继续指向你不希望它指向的东西。因此,如果您不希望指针再指向旧的东西,将指针设置为 null 绝对是一种很好的做法。

除了抛出异常的非常好点(适用于C++),即使在 C 中也是如此,初始化所有变量也是一个好主意。编译器几乎总是在确定不需要初始化时优化初始化。

这里有一个小例子,说明如果你不这样做会发生什么。

SomeType* ptr;
ptr = SomeMethod(some, params);

如您所见,这工作正常,没有问题ptr没有有效值。

现在,有人决定添加更多代码是个好主意:

SomeType* ptr;
int x = someotherfunction;
if (x > 90)
{
     ptr = SomeMethod(some, params);
}
现在突然间

,您的ptr将有一些随机的废话内容 - 可能是 NULL,但很可能是其他内容。是的,我们都认为我们会记得回来检查一下,看看我们的更改是否影响了其他东西,等等。但是如果你已经编程了几年,我几乎可以肯定你已经遇到过一些"哎呀,没想过"的情况。

想象一下,我添加"someotherfunction"的新代码是 20 或 30 行,您可以清楚地看到问题所在。

在第一种情况下,最好在声明新值时始终分配一个值,这样您就不会最终得到单位化值(一种保护您免受自己的错误)。但是,如果它直接彼此相继,则可以被视为无用。

在第二种情况下,它是完全没用的。

它确实没用(这被称为"死任务")。但是,有些人更喜欢在声明时初始化指向NULL的指针,然后分别显式分配给它。也许这只是出于可读性的原因(也许有些人认为它更具可读性,或者发现即使例如,赋值被注释掉以进行调试也很有用)。我不确定我会这样做/认为这是实践。

另请注意,因此,大多数编译器会自动优化赋值。

这种做法不仅无用,而且有害。如果你刚刚写:

SomeType* ptr = NULL;
/* lots of stuff in between */
ptr = SomeMethod(some, params);

并且不小心在干预代码中的某处使用了ptr,编译器将无法通知您此错误。如果你写:

SomeType* ptr;
/* lots of stuff in between */
ptr = SomeMethod(some, params);

那么在赋值之前使用 ptr 就是 UB,一个好的编译器或静态分析工具会通知您此错误。

代码现在毫无用处,但也许使用预测了未来的维护,其中将在冗余初始化和赋值之间添加更多行,以便初始化不再是多余的。

该代码也可能是删除的结果。也就是说,声明和赋值之间可能存在一些代码,但后来被删除了,并且没有进行任何清理以将赋值合并到初始化中。当然,代码是没有意义的;在这种情况下,我们只是有一个关于它是如何变成那样的历史解释(也许还有改变它的理由)。

有时,看似无用的变量初始化是由于有人不得不使编译器警告"可能未使用"变量静音而发生的,如果有多种方法可以访问使用该变量的代码块,并且编译器不够复杂,无法证明在所有情况下变量都以某种方式通过赋值初始化,则可能会发生这种情况。

在声明变量的位置初始化所有变量是一个好习惯,因为它减少了由于未初始化的数据而导致不可预测行为的可能性。一些人认为,当未初始化的变量被初始化所消除时,某些静态工具的效果会降低,这些初始化会给它们不适当的值,从而使错误更难找到。但是,如果错误基于初始化的数据,则它们更具可重复性,并且错误行为很可能也可以在平台之间移植。某些语言会为您初始化本地变量。在Lisp中,(let (x) ...)表示在代码块...中,变量x的值为NIL,因为没有初始值设定项。Lisp 代码的静态分析可以很容易地跟踪事实,例如NIL被不恰当地传递给数字函数。 在C和相关语言中,问题略有不同,因为对于像int这样的类型,没有等效的错误类型值,例如NIL。 因此0被替换,这是一个有效的值,不会简单地用类型不匹配来破坏计算。不适当的0可能会导致计算中的算法错误。然而,在指针的情况下,空指针值是NIL的合理传真,因为它是一个程序员可见的可移植域值,上面写着"我不指向任何对象"。当指针实际上暂时不指向任何东西时,我们应该给它这个值,而不是在其中留下随机位,这可能会意外地指向一个意外的对象。