在c++的早期,当它被固定在C的顶部时,你不能使用NULL,因为它被定义为(void*)0。你不能将NULL赋值给除void*以外的任何指针,这使得它有点无用。在那些日子里,人们接受使用0(零)作为空指针。

直到今天,我仍然使用0作为空指针,但我周围的人坚持使用null。我个人认为给一个现有的值命名(NULL)没有任何好处-因为我也喜欢将指针作为真值测试:

if (p && !q)
  do_something();

那么使用0就更有意义了(就像如果你使用NULL,你不能在逻辑上使用p && !q -你需要显式地与NULL进行比较,除非你假设NULL为零,在这种情况下为什么要使用NULL)。

是否有任何客观的原因让人们更喜欢0而不是NULL(反之亦然),或者这只是个人偏好?

编辑:我应该补充(最初的意思是说),对于RAII和异常,我很少使用零/NULL指针,但有时你仍然需要它们。


当前回答

我主张在任何可能的情况下都不要使用0或NULL指针。

使用它们迟早会导致你的代码出现分段错误。根据我的经验,指针是c++中最大的bug来源之一

此外,它还会导致在整个代码中出现“if-not-null”语句。如果您可以依赖始终有效的状态,那就更好了。

几乎总是有更好的选择。

其他回答

如果我回忆正确,NULL在我使用的头中定义不同。对于C,它被定义为(void*)0,而对于c++,它被定义为0。代码看起来像这样:

#ifndef __cplusplus
#define NULL (void*)0
#else
#define NULL 0
#endif

就我个人而言,我仍然使用NULL值来表示空指针,这表明你使用的是指针而不是某种整型。是的,在内部NULL值仍然是0,但它不是这样表示的。

此外,我不依赖于整数到布尔值的自动转换,而是显式地比较它们。

例如,更喜欢使用:

if (pointer_value != NULL || integer_value == 0)

而不是:

if (pointer_value || !integer_value)

可以这么说,这在c++ 11中都得到了纠正,可以简单地使用nullptr而不是NULL,也可以使用nullptr的类型nullptr_t。

将指针设置为0并不那么清楚。特别是如果你使用c++以外的语言。这包括C语言和Javascript。

我最近用这样的代码删除:

DrawTo(BITMAP *buffer) =0;

第一次为纯虚函数。我以为这只是一个星期的魔术表演。当我意识到它基本上只是将函数指针设置为空(因为在c++的大多数情况下虚函数只是函数指针)时,我踢了自己一脚。

DrawTo(BITMAP *buffer) =null;

如果我的新眼睛没有间隔的话就不会那么令人困惑了。实际上,我想知道为什么c++不使用小写的null,就像它现在使用小写的false和true一样。

我尽量使用c++参考来避免整个问题。而不是

void foo(const Bar* pBar) { ... }

你可能经常会写作

void foo(const Bar& bar) { ... }

当然,这并不总是有效的;但是空指针可能会被过度使用。

使用0或NULL都有相同的效果。

然而,这并不意味着它们都是很好的编程实践。鉴于在性能上没有差异,选择低级感知选项而不是不可知论/抽象选项是一种糟糕的编程实践。帮助代码的读者理解您的思维过程。

NULL, 0,0.0, '\0', 0x00和其他东西都转换为相同的东西,但在你的程序中是不同的逻辑实体。它们应该这样使用。NULL是指针,0是数量,0x0是位感兴趣的值,等等。无论指针是否编译,都不能将'\0'赋值给它。

我知道一些社区鼓励通过打破环境契约来展示对环境的深入了解。然而,负责任的程序员会编写可维护的代码,并将此类实践排除在他们的代码之外。

我想说,历史已经证明了这一点,那些主张使用0(零)的人是错误的(包括Bjarne Stroustrup)。支持0的理由主要是审美和“个人偏好”。

c++ 11创建后,使用新的nullptr类型,一些编译器开始抱怨(使用默认形参)将0传递给带有指针参数的函数,因为0不是指针。

如果代码是使用NULL编写的,那么可以通过代码库执行简单的搜索和替换,使其成为nullptr。如果您被使用0作为指针编写的代码所困扰,那么更新它将变得更加乏味。

如果你现在必须为c++ 03标准编写新代码(并且不能使用nullptr),你真的应该只使用NULL。这将使您将来更容易更新。