在C ++的早期,当它被用螺栓固定在C之上时,你不能使用NULL,因为它被定义为(void*)0
。您无法为除void*
以外的任何指针指定NULL,这使得它变得毫无用处。在那些日子里,人们接受了你使用0
(零)作为空指针。
到今天,我继续使用零作为空指针,但我周围的人坚持使用NULL
。我个人认为给现有值命名(NULL
)没有任何好处 - 因为我也喜欢将指针测试为真值:
if (p && !q)
do_something();
然后使用零更有意义(如果您使用NULL
,则无法在逻辑上使用p && !q
- 您需要明确地与NULL
进行比较,除非您假设{{1} }为零,在这种情况下为什么要使用NULL
)。
有没有客观的理由偏好零而不是NULL(反之亦然),或者只是个人偏好?
编辑:我应该添加(并且最初要说)使用RAII和异常,我很少使用零/空指针,但有时你确实需要它们。
答案 0 :(得分:171)
这是Stroustrup对此的看法:C++ Style and Technique FAQ
在C ++中,
NULL
的定义为0,因此只有美学差异。我更喜欢避免宏,所以我使用0.NULL
的另一个问题是人们有时会错误地认为它与0不同和/或不是整数。在预标准代码中,NULL
有时被定义为不适合的东西,因此必须/必须避免。这些日子不太常见。如果必须命名空指针,请将其命名为
nullptr
;这就是它在C ++ 11中所称的内容。然后,nullptr
将成为关键字。
那就是说,不要让小东西流汗。
答案 1 :(得分:119)
有一些论点(其中一个是相对较新的),我认为这与Bjarne的立场相矛盾。
使用NULL
可以搜索它的使用情况,并且还强调开发人员想要使用NULL
指针,无论编译器是否正在解释它如NULL
或不。{/ p>
每个人引用的例子是:
void foo(int*);
void foo (int);
void bar() {
foo (NULL); // Calls 'foo(int)'
}
但是,至少在我看来,上面的问题并不是我们对空指针常量使用NULL,而是我们有'foo'的重载,这些重载采用了不同类型的参数。参数也必须是int
,因为任何其他类型都会导致模糊调用,因此生成有用的编译器警告。
即使没有C ++ 0x,现在还有一些工具可以验证NULL
是否用于指针,而0
用于整数类型。
std::nullptr_t
类型。 这是该表的最新参数。 0
和NULL
的问题正在为C ++ 0x主动解决,并且您可以保证对于提供NULL
的每个实现,他们将要做的第一件事是:
#define NULL nullptr
对于那些使用NULL
而不是0
的人来说,改变将是类型安全的改进,很少或没有努力 - 如果有的话,它也可能会捕获他们使用过的一些错误NULL
0
。对于今天使用0
的任何人......呃......希望他们对正则表达式有很好的了解......
答案 2 :(得分:44)
使用NULL。 NULL显示您的意图。它是0是一个无关紧要的实现细节。
答案 3 :(得分:35)
我总是使用:
NULL
指针'\0'
for chars 0.0
用于花车和双打其中0表示可以。这是信号意图的问题。那就是说,我不是肛门。
答案 4 :(得分:34)
我很久以前就停止了使用NULL(和大多数其他宏一样)。我这样做不仅是因为我想尽可能地避免使用宏,而且因为NULL似乎已经在C和C ++代码中被过度使用了。它似乎只在需要0值时使用,而不仅仅是指针。
在新项目中,我将其放在项目标题中:
static const int nullptr = 0;
现在,当符合C ++ 0x的编译器到达时,我所要做的就是删除该行。 这样做的一个很好的好处是Visual Studio已经将nullptr识别为关键字并对其进行适当的突出显示。
答案 5 :(得分:20)
cerr << sizeof(0) << endl;
cerr << sizeof(NULL) << endl;
cerr << sizeof(void*) << endl;
============
On a 64-bit gcc RHEL platform you get:
4
8
8
================
故事的寓意。在处理指针时应该使用NULL。
1)它声明了你的意图(不要让我搜索你的所有代码,试图弄清楚变量是指针还是某种数字类型)。
2)在某些期望变量参数的API调用中,它们将使用NULL指针来指示参数列表的结尾。在这种情况下,使用“0”而不是NULL可能会导致问题。在64位平台上,va_arg调用需要一个64位指针,但是你只会传递一个32位整数。对我来说,就像你依赖其他32位为你清零一样?我已经看到某些编译器(例如Intel的icpc)并不那么优雅 - 这导致了运行时错误。
答案 6 :(得分:16)
如果我没记错的话,在我使用的标题中定义的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_t
使用{{1}的类型}}
答案 7 :(得分:14)
我会说历史已经说过了,并且赞成使用0(零)的人是错的(包括Bjarne Stroustrup)。支持0的论据主要是美学和“个人偏好”。
使用新的nullptr类型创建C ++ 11之后,一些编译器开始抱怨(使用默认参数)将0传递给带有指针参数的函数,因为0不是指针。
如果代码是使用NULL编写的,则可以通过代码库执行简单的搜索和替换,以使其成为nullptr。如果您对使用0选择作为指针编写的代码感到困惑,那么更新它会更加繁琐。
如果你现在必须编写新的代码到C ++ 03标准(并且不能使用nullptr),你真的应该使用NULL。这将使您将来更容易更新。
答案 8 :(得分:11)
我通常使用0.我不喜欢宏,并且无法保证您使用的某些第三方标头不会重新定义NULL以使其变得奇怪。
您可以使用Scott Meyers和其他人提出的nullptr对象,直到C ++获得nullptr关键字:
const // It is a const object...
class nullptr_t
{
public:
template<class T>
operator T*() const // convertible to any type of null non-member pointer...
{ return 0; }
template<class C, class T>
operator T C::*() const // or any type of null member pointer...
{ return 0; }
private:
void operator&() const; // Can't take address of nullptr
} nullptr = {};
Google“nullptr”了解更多信息。
答案 9 :(得分:11)
我曾经在一台机器上工作,其中0是有效地址,NULL被定义为一个特殊的八进制值。在那台机器上(0!= NULL),所以代码如
char *p;
...
if (p) { ... }
无法按预期工作。你必须写
if (p != NULL) { ... }
虽然我相信大多数编译器现在将NULL定义为0,但我仍然记得那些年前的教训:NULL不一定是0。
答案 10 :(得分:9)
使用0或NULL将产生相同的效果。
但是,这并不意味着它们都是良好的编程习惯。鉴于性能没有差异,在不可知/抽象替代方案上选择低级别感知选项是一种糟糕的编程习惯。 帮助您的代码读者理解您的思维过程。
NULL,0,0.0,'\ 0',0x00和whatelse都转换为相同的东西,但是程序中的逻辑实体不同。它们应该这样使用。 NULL是一个指针,0是数量,0x0是一个有趣的位等等。无论是否编译,都不会将“\ 0”指定给指针。
我知道有些社区鼓励通过破坏环境合同来展示对环境的深入了解。但是,负责任的程序员会制作可维护的代码,并将这些实践排除在代码之外。
答案 11 :(得分:9)
我认为标准保证NULL == 0,所以你可以做到。我更喜欢NULL,因为它记录了你的意图。
答案 12 :(得分:5)
奇怪,没有人,包括Stroustroup提到过。在谈论标准和美学时,没有人注意到在0
中使用NULL
代替危险,例如,在sizeof(int) != sizeof(void*)
的架构中使用0
{ {1}}。和Stroustroup一样,出于审美原因,我更喜欢{{1}},但是必须注意不要在类型可能不明确的地方使用它。
答案 13 :(得分:4)
我尝试尽可能使用C ++引用来避免整个问题。而不是
void foo(const Bar* pBar) { ... }
你可能经常能够写
void foo(const Bar& bar) { ... }
当然,这并不总是奏效;但是空指针可能被过度使用。
答案 14 :(得分:3)
我更喜欢使用NULL,因为它清楚表明你的意图是值表示指针而不是算术值。事实上,这是一个宏观是不幸的,但由于它是如此广泛根深蒂固,所以没有什么危险(除非有人做了一些真正的蠢事)。我希望它从一开始就是一个关键词,但你能做什么?
那就是说,我将指针用作真值本身没有问题。就像NULL一样,它是一个根深蒂固的习语。
C ++ 09将添加nullptr构造,我认为该构造早就应该了。
答案 15 :(得分:3)
主要是个人偏好,尽管有人可以提出NULL的论点,很明显该对象是一个当前没有指向任何东西的指针,例如。
void *ptr = &something;
/* lots o' code */
ptr = NULL; // more obvious that it's a pointer and not being used
论证的另一个方面是你是否应该使用逻辑比较(隐式强制转换为bool)或明确检查NULL,但这也归结为可读性。
答案 16 :(得分:3)
我和Stroustrup在这一个:-) 由于NULL不是语言的一部分,我更喜欢使用0。
答案 17 :(得分:1)
我总是使用0.不是因为任何真正考虑过的原因,只是因为当我第一次学习C ++时,我读了一些推荐使用0的东西,而我总是那样做。从理论上讲,可读性可能存在混淆问题,但在实践中,我从未在数千个工时和数百万行代码中遇到过这样的问题。正如Stroustrup所说,在标准成为nullptr之前,这只是个人审美问题。
答案 18 :(得分:1)
有人告诉我一次......我要将NULL重新定义为69.从那以后我不使用它:P
它使您的代码非常容易受到攻击。
修改强>
并非标准中的所有内容都是完美的。宏NULL是一个实现定义的C ++空指针常量,与C NULL宏不完全兼容,除了隐藏类型隐式转换它在无用且容易出错的工具中。
NULL不会表现为空指针,而是表现为O / OL文字。
告诉我下一个例子并不令人困惑:
void foo(char *);
void foo(int);
foo(NULL); // calls int version instead of pointer version!
正因为如此,在新标准中出现了std :: nullptr_t
如果您不想等待新标准并且想要使用nullptr,请使用至少像Meyers建议的那样(请参阅jon.h评论)。
答案 19 :(得分:1)
嗯,我认为尽可能不使用0或NULL指针。
使用它们迟早会导致代码中的分段错误。根据我的经验,gereral中的指针是C ++中最大的错误来源之一
此外,它会导致代码中出现“if-not-null”语句。如果你可以完全依赖有效状态,那就更好了。
几乎总会有更好的选择。
答案 20 :(得分:-4)
将指针设置为0并不是那么清楚。特别是如果你使用C ++以外的语言。这包括C和Javascript。
我最近使用了一些代码:
virtual void DrawTo(BITMAP *buffer) =0;
第一次用于纯虚函数。我认为这是一个神奇的jiberjash一个星期。当我意识到它基本上是将函数指针设置为null
时(因为虚函数在大多数情况下只是C ++的函数指针)我自己踢了。
virtual void DrawTo(BITMAP *buffer) =null;
null
,就像现在使用小写的false和true一样。