你在C ++中使用NULL或0(零)指针?

在C ++的早期,当它被locking在C之上时,你不能使用NULL,因为它被定义为(void*)0 。 除了void* ,你不能将NULL赋值给任何指针,这使得它无用。 在那些日子里,已经接受你使用0 (零)作为空指针。

到目前为止,我一直使用零作为空指针,但是我周围的人坚持使用NULL 。 我个人认为给一个现有的值赋予一个名字( NULL )没有任何好处 – 因为我也喜欢把指针作为真值来testing:

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

那么使用零更有意义(如果你使用NULL ,你不能逻辑上使用p && !q – 你需要明确地比较NULL ,除非你假设NULL是零,在这种情况下为什么使用NULL )。

有没有客观的理由更喜欢零(或反之亦然),或者只是个人喜好?

编辑:我应该添加(原本是说)与RAII和exception,我很less使用零/ NULL指针,但有时你仍然需要它们。

这里是Stroustrup的: C ++风格和技巧常见问题

在C ++中, NULL的定义是0,所以只有一个美学的区别。 我宁愿避免macros,所以我使用0. NULL另一个问题是人们有时错误地认为它是从0和/或不是一个整数不同。 在预标准代码中, NULL有时被定义为不合适的东西,因此必须避免。 这些日子不太常见。

如果你必须命名空指针,则称它为nullptr ; 这就是它在C ++ 11中所称的。 那么, nullptr将是一个关键字。

也就是说,不要为了小东西而stream汗。

有几个论点(其中一个是相对较新的),我认为这与Bjarne的立场相矛盾。

  1. 意向文件

使用NULL允许对其进行search,而且还强调开发人员希望使用NULL指针,而不pipe它是否被编译器解释为NULL

  1. 指针和“int”的重载比较less见

大家引用的例子是:

 void foo(int*); void foo (int); void bar() { foo (NULL); // Calls 'foo(int)' } 

不过,至less在我看来,上面的问题并不是我们对空指针常量使用NULL,而是我们有重载“foo”的参数,它们采用了非常不同的参数。 该参数也必须是int ,因为任何其他types都会导致模糊的调用,因此会生成有用的编译器警告。

  1. 分析工具可以帮助今天!

即使在没有C ++ 0x的情况下,也有一些可用的工具可以validationNULL是否用于指针,而0则用于整型。

  1. C ++ 11将有一个新的std::nullptr_ttypes。

这是表格的最新说法。 对于C ++ 0x, 0NULL的问题正在被主动解决,并且可以保证对于每个提供NULL实现,他们要做的第一件事是:

 #define NULL nullptr 

对于那些使用NULL而不是0 ,这种改变将会在types安全性方面有所改进,只需要很less的努力或者没有任何的努力 – 如果有的话,它们也可以在0使用NULL来捕获一些错误。 对于任何人今天使用0 …呃…希望他们有正则expression式的良好知识…

使用NULL。 NULL显示你的意图。 这是0是一个实施细节应该不重要。

我停止使用NULL,而不是很久以前(以及其他大多数macros)。 我这样做不仅是因为我想尽可能地避免macros,而且因为NULL似乎已经被C和C ++代码所使用。 这似乎是使用任何时候需要一个0值,而不仅仅是指针。

在新的项目中,我把它放在项目标题中:

 static const int nullptr = 0; 

现在,当符合C ++ 0x的编译器到达时,我所要做的就是删除该行。 这样做的一个好处是,Visual Studio已经将nullptr识别为关键字并且适当地突出显示它。

我总是使用:

 NULL for pointers '\0' for chars 0.0 for floats and doubles 

0会做的很好。 这是一个信号意图的问题。 那就是说,我不是肛门的。

  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)它声明你的意图(不要让我search你的代码,试图找出一个variables是否是一个指针或一些数字types)。

2)在某些需要可变参数的API调用中,它们将使用NULL指针来指示参数列表的结尾。 在这种情况下,使用“0”而不是NULL可能会导致问题。 在64位平台上,va_arg调用需要一个64位的指针,但是只传递一个32位的整数。 对我来说,就像你依靠其他的32位为你清零? 我见过某些编译器(例如Intel的icpc),这些编译器并不那么亲切 – 这导致了运行时错误。

如果我正确地记得NULL在我使用的标题中定义不同。 对于C,它被定义为(void *)0,对于C ++,它被定义为0。

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

就我个人而言,我仍然使用NULL值来表示空指针,它使得它明确指出你正在使用一个指针,而不是一些整数types。 是的内部NULL值仍然是0,但它不是这样表示。

此外,我不依赖于整数自动转换为布尔值,但明确地比较它们。

例如,喜欢使用:

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

而不是:

 if (pointer_value || !integer_value) 

我们只需要说明这一点,在C ++ 11中可以简单地使用nullptr而不是NULL ,而且也是nullptrtypes的nullptr_t

我通常使用0.我不喜欢macros,也不能保证你使用的第三方头不会重新定义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 TC::*() const // or any type of null member pointer... { return 0; } private: void operator&() const; // Can't take address of nullptr } nullptr = {}; 

谷歌“nullptr”的更多信息。

我曾经在一台机器上工作,其中0是一个有效的地址,NULL被定义为一个特殊的八进制值。 在那台机器上(0!= NULL),所以代码如

 char *p; ... if (p) { ... } 

不会像你期望的那样工作。 你必须写

 if (p != NULL) { ... } 

虽然我相信大多数编译器现在将NULL定义为0,但我还记得那些年前的教训:NULL不一定是0。

我认为标准保证NULL == 0,所以你可以做。 我更喜欢NULL,因为它logging你的意图。

我会说历史已经说了,而那些赞成使用0(零)的人是错误的(包括Bjarne Stroustrup)。 赞成0的论点主要是美学和“个人喜好”。

在创buildC ++ 11之后,有了新的nullptrtypes,一些编译器开始抱怨(使用默认参数)将0传递给带指针参数的函数,因为0不是指针。

如果代码是使用NULL编写的,则可以通过代码库执行简单的search和replace,以使其成为nullptr。 如果你使用0作为指针来编写代码,那么更新它就更加单调乏味了。

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

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

但是,这并不意味着它们都是很好的编程实践。 考虑到性能没有差别,select一个低层次的选项而不是不可知的/抽象的select是一个糟糕的编程实践。 帮助你的代码读者理解你的思维过程

NULL,0,0.0,'\ 0',0x00和whatelse都转换为相同的东西,但在你的程序中是不同的逻辑实体。 他们应该这样使用。 NULL是一个指针,0是数量,0x0是一个值,其位有趣等你不会分配'\ 0'指针是否编译。

我知道一些社区鼓励通过破坏环境合同来展示对环境的深入了解。 负责任的程序员,但是,使可维护的代码,并保持这些做法的代码。

奇怪的是,没有人,包括Stroustroup提到。 在谈论标准和美学时,没有人注意到在NULL使用0危险的,例如,在sizeof(int) != sizeof(void*)的体系结构的variables参数列表中。 就像Stroustroup一样,由于美学的原因,我更喜欢0 ,但是我们应该小心,不要在types可能模糊的地方使用它。

我尝试通过在可能的情况下使用C ++引用来避免整个问题。 而不是

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

你可能经常能写

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

当然,这并不总是工作。 但空指针可以被过度使用。

我和Stroustrup在这一个:-)由于NULL不是语言的一部分,我更喜欢使用0。

我更喜欢使用NULL,因为它表明你的意图是值表示一个指针而不是一个算术值。 这是一个macros观的事实是不幸的,但由于它是如此广泛的根深蒂固,没有什么危险(除非有人做了一些真正的骨头)。 我希望它从一开始就是一个关键字,但你能做什么?

也就是说,我用指针作为真值本身没有问题。 就像NULL一样,这是一个根深蒂固的成语。

C ++ 09将会添加我认为应该迟到的nullptr结构。

大多数情况下,个人偏好,虽然可以使NULL的说法很明显,该对象是一个指针,目前不指向任何东西,例如

 void *ptr = &something; /* lots o' code */ ptr = NULL; // more obvious that it's a pointer and not being used 

IIRC,标准并不要求NULL为0,所以使用<stddef.h>中定义的任何内容对您的编译器来说可能是最好的。

争论的另一个方面是你是否应该使用逻辑比较(隐式转换为bool)或者显式检查NULL,但这也归结为可读性。

我总是使用0.不是任何真正想到的理由,只是因为当我第一次学习C ++时,我阅读了一些推荐使用0的东西,而且我总是这样做。 从理论上讲,可读性是一个混淆的问题,但在实践中我从来没有遇到过几千个工时和几百万行代码的问题。 正如Stroustrup所说,在标准变为nullptr之前,这只是个人的美学问题。

有人告诉我一次…我要重新定义NULL为69.从那时起我不使用它:P

它使你的代码非常脆弱。

编辑:

并非标准中的所有内容都是完美的。 macrosNULL是一个实现定义的C ++空指针常量,与C NULLmacros不完全兼容,除了types隐藏隐式转换它在一个无用的和容易出错的工具。

NULL不performance为空指针,而是O / OL文字。

告诉我下一个例子并不令人困惑:

 void foo(char *); void foo(int); foo(NULL); // calls int version instead of pointer version! 

是因为这一点,在新的标准出现std :: nullptr_t

如果你不想等待新标准,并想使用nullptr,那么至less应该使用像Meyers所build议的那样的体系(见jon.h comment)。

那么我认为只要有可能就不要使用0或NULL指针。

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

另外,它会导致遍布代码的“if-not-null”语句。 如果你总是可以依赖一个有效的状态,那就好多了。

几乎总是有一个更好的select。

将指针设置为0就不那么清楚了。 尤其是如果你使用C ++以外的语言。 这包括C以及Javascript。

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

virtual void DrawTo(BITMAP *buffer) =0;

为纯虚function首次。 我认为这是一个星期的一些神奇的jiberjash。 当我意识到它只是基本上将函数指针设置为null (因为在大多数情况下,对于C ++来说,虚函数只是函数指针),我踢了自己。

virtual void DrawTo(BITMAP *buffer) =null;

如果没有适当的间距,我的新眼睛可能会比那种枯燥乏味的东西混乱。 实际上,我想知道为什么C ++不使用小写的null ,就像现在使用小写的false和true一样。