当前位置:  开发笔记 > 编程语言 > 正文

对C++中的指针使用NULL或0(零)吗?

如何解决《对C++中的指针使用NULL或0(零)吗?》经验,为你挑选了13个好方法。

在C++的早期,当它被用螺栓固定在C之上时,你不能使用NULL,因为它被定义为(void*)0.你不能将NULL分配给除了之外的任何指针void*,这使得它变得毫无用处.在那些日子里,人们接受了你使用0(零)空指针.

直到今天,我继续使用零作为空指针,但我周围的人坚持使用NULL.我个人认为给NULL现有值一个name()没有任何好处- 因为我也喜欢将指针测试为真值:

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

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

有没有客观的理由偏好零而不是NULL(反之亦然),或者只是个人偏好?

编辑:我应该添加(并且最初要说)使用RAII和异常,我很少使用零/ NULL指针,但有时你确实需要它们.



1> Martin Cote..:

这是Stroustrup对此的看法:C++ Style and Technique FAQ

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

如果必须命名空指针,请调用它nullptr; 这就是它在C++ 11中所称的内容.然后,nullptr将是一个关键字.

也就是说,不要让小东西流汗.


Bjarne在C++ 0x开始处理新的null类型之前写了这个.当它可用于平台时,将会使用NULL这种类型的情况,我认为你会看到关于此的普遍共识的C变化.

2> Richard Cord..:

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

    意图文件

使用NULL允许搜索它的使用,它还强调开发人员想要使用NULL指针,无论编译器是否正在解释它NULL.

    指针和'int'的重载相对较少

每个人引用的例子是:

void foo(int*);
void foo (int);

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

但是,至少在我看来,上面的问题并不是我们对空指针常量使用NULL,而是我们有'foo'的重载,这些重载采用了不同类型的参数.该参数也必须是一个int,因为任何其他类型都会导致模糊调用,因此生成一个有用的编译器警告.

    分析工具可以帮助今天!

即使在没有C++ 0x的情况下,现在还有一些工具可用于验证NULL用于指针的工具,以及0用于整数类型的工具.

    C++ 11将有一个新std::nullptr_t类型.

这是该表的最新参数.C++ 0x 的问题0NULL正在积极解决,你可以保证,对于提供的每个实现NULL,他们将要做的第一件事是:

#define NULL  nullptr

对于那些谁使用NULL,而不是0,这种变化将在很少或根本没有力气类型安全性的提高-如果有的话,还可以赶上他们已经使用了一些错误NULL0.对于0今天使用的任何人......呃......希望他们对正则表达有很好的了解......


`#define NULL nullptr`似乎很危险.无论好坏,许多遗留代码对0以外的东西使用NULL.例如,句柄通常实现为某种整数类型,并将它们设置为"NULL"并不罕见.我甚至看到过使用`NULL`将`char`设置为零终结符的滥用行为.
@AdrianMcCarthy:我只会说,如果存在代码默默编译并具有不同含义的危险,那将是危险的.我很确定事实并非如此,所以实际上会检测到所有不正确的NULL用法.
@RichardCorden:嗯,假设`NULL`的其他用法实际上是不正确的.许多API长期以来都使用带句柄的"NULL",这实际上是许多API的文档用法.突然打破这些并声明他们做错了并不务实.
@Richard,为什么不这样做呢?您可以使用Meyers nullptr_t然后当0x可用时删除`#include`并一直保持安全.

3> Andy Lester..:

使用NULL.NULL显示您的意图.它是0是一个无关紧要的实现细节.


0不是实现细节.标准将0定义为任何位模式表示空指针.
我知道它是标准的一部分.就读代码而言,这是一个实现细节.读者应该认为"NULL指针"不是"0,在这种情况下,它指的是NULL指针,而不是我可以用算术进行算术的数字."
好像.. !! Dude,C++是一种低级语言!使用0,这是一个众所周知的习语.
+1.同意安迪.@Ferruccio,程序员的想法的实现*细节*与编译器的实现*定义不同*

4> Andrew Stein..:

我一直用:

NULL 指针

'\0' 为了chars

0.0 用于浮动和双打

其中0会很好.这是信号意图的问题.那就是说,我不是肛门.


ya可能应该使用0.0F表示浮点数,以避免隐式类型转换

5> Ferruccio..:

我很久以前就停止使用NULL(和大多数其他宏一样).我这样做不仅是因为我想尽可能地避免使用宏,而且因为NULL似乎已经在C和C++代码中被过度使用了.它似乎只在需要0值时使用,而不仅仅是指针.

在新项目中,我将其放在项目标题中:

static const int nullptr = 0;

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


我不同意.在编译器赶上之前,它在短期内将不那么便携.从长远来看,它将具有可移植性,可能更具可读性.
使用NULL将更长期可移植.'nullptr'将适用于某些平台,而不适用于其他平台.此处的解决方案要求您在声明周围使用预处理器,以确保它仅在需要时出现.NULL将自动执行此操作.
另外,对于非C++ 0x编译器,总是可以#define nullptr NULL.

6> 小智..:
    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)并不那么优雅 - 这导致了运行时错误.



7> Daemin..:

如果我没记错的话,在我使用的标题中定义了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就是a的类型nullptr.



8> 小智..:

我会说历史已经说过,那些赞成使用0(零)的人是错的(包括Bjarne Stroustrup).支持0的论据主要是美学和"个人偏好".

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

如果代码是使用NULL编写的,则可以通过代码库执行简单的搜索和替换,以使其成为nullptr.如果您遇到使用0选择作为指针编写的代码,则更新它会更加繁琐.

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



9> mxg..:

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

char *p;

...

if (p) { ... }

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

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

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


您没有使用兼容的编译器.标准说NULL*是*0并且编译器应该在指针上下文中将0转换为适当的真值NULL值.
是的,你是对的.这是在ANSI生产C标准之前的80年代中期.那时没有合规性,编译器编写者可以自由地解释他们认为合适的语言.这就是为什么需要标准的原因.

10> jon-hanson..:

我通常使用0.我不喜欢宏,并且不能保证您使用的某些第三方标头不会将NULL重新定义为奇怪的东西.

您可以使用Scott Meyers和其他人提出的nullptr对象,直到C++获得nullptr关键字:

const // It is a const object...
class nullptr_t 
{
public:
    template
    operator T*() const // convertible to any type of null non-member pointer...
    { return 0; }

    template
    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"了解更多信息.


任何第三方库定义NULL以外的任何东西(如果被编译为C代码,则为`(void*)0`)只是要求麻烦而不应该使用.
你有没有真正看到一个重新定义NULL的库?自从?如果这样的库曾经存在过,那么你会遇到比重新定义的NULL更大的问题,比如你正在使用一个足以重新定义NULL的库.
"不喜欢宏"是对象#define的奇怪批判.也许你的意思是说你不喜欢C预处理器?

11> Mark Ransom..:

我认为标准保证NULL == 0,所以你可以做到.我更喜欢NULL,因为它记录了你的意图.



12> Chris..:

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

但是,这并不意味着它们都是良好的编程实践.鉴于性能没有差异,在不可知/抽象替代方案上选择低级别感知选项是一种糟糕的编程习惯.帮助您的代码读者理解您的思考过程.

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

我知道一些社区鼓励通过违反环境合同来展示对环境的深入了解.但是,负责任的程序员可以编写可维护的代码,并将这些实践保留在代码之外.



13> Michael Krel..:

奇怪,没有人,包括Stroustroup提到的那个.虽然谈论了很多的标准和美学没有人注意到它是危险的使用0NULL的代替,例如,在变量参数列表上的架构,其中sizeof(int) != sizeof(void*).像Stroustroup一样,我更喜欢0美学原因,但是必须小心不要在类型可能不明确的地方使用它.

推荐阅读
echo7111436
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有