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