24

我见过很多这样的代码:

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

重点是什么?我还看到它在ptr其他地方声明(例如在类定义中),然后在类构造函数中会有这样的:

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

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

4

6 回答 6

34

如果“SomeMethod”引发异常,您的 SomeType* 将继续指向您不希望它指向的东西。因此,如果您不希望指针再指向旧的东西,将指针设置为 null 绝对是一个好习惯。

于 2013-01-28T19:55:40.447 回答
16

除了适用于 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 行,您可以清楚地看到问题所在。

于 2013-01-28T20:02:41.530 回答
3

在第一种情况下,在声明新值时始终分配一个值是一种很好的做法,因此您最终不会得到统一的值(保护您免受自己的错误)。但是,如果直接一个接一个,就可以看作是无用的。

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

于 2013-01-28T19:56:23.940 回答
2

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

另请注意,大多数编译器会自动优化分配。

于 2013-01-28T19:56:34.893 回答
2

这种做法不仅没有用;这是有害的。如果你刚刚写了:

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,一个好的编译器或者静态分析工具会通知你这个错误。

于 2013-01-28T21:04:48.067 回答
1

代码现在是无用的,但也许使用预期将来的维护,其中将在冗余初始化和分配之间添加更多行,以便初始化不再是冗余的。

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

有时,看似无用的变量初始化是由于有人不得不让编译器对“可能未使用”的变量发出警告,如果有不止一种方法可以到达使用该变量的代码块,就会发生这种情况,并且编译器不够复杂,无法证明在所有情况下,变量都是通过赋值以某种方式初始化的。

在声明它们的地方初始化所有变量是一个好习惯,因为它减少了由于未初始化数据而导致的不可预测行为的可能性。一些人认为,当未初始化的变量被赋予不适当值的初始化所消除时,某些静态工具的工作效果会较差,从而使错误更难被发现。但是,如果错误基于初始化数据,则它们的可重复性更高,并且错误行为也很可能在平台之间也可移植。某些语言会为您初始化本地人。在 Lisp 中, (let (x) ...) 意味着在代码块...中,变量x的值为NIL,因为没有初始化程序。Lisp 代码的静态分析可以轻松追踪诸如NIL被不恰当地传递给数值函数。在 C 和相关语言中,问题有点不同,因为对于 type like int,没有等价的错误类型值,例如NIL. So0被替换,这是一个有效值,不会简单地因类型不匹配而破坏计算。不适当的0可能会导致计算中的算法错误。然而,在指针的情况下,空指针值是一个合理的复制品,NIL因为它是程序员可见的、可移植的域值,上面写着“我不指向任何对象”。当指针实际上暂时没有指向任何东西时,我们应该给它这个值,而不是在其中留下可能意外指向意外对象的随机位。

于 2013-01-28T23:03:33.653 回答