NULL与nullptr(为什么被替换?)

337

我知道在C++中,指针应用程序中的0xNULLnullptr替代。我只是好奇他们为什么做出了这个更改的确切原因?

使用nullptr而不是NULL处理指针时,在哪种情况下会更有优势?


3
@BryanChen 不是这样的。我不想知道nullptr是什么...我想知道为什么要实现它,如果你正确地阅读问题,收益是什么。 - Riptyde4
2
请阅读此答案 - Bryan Chen
7
@BryanChen提到了一些我不熟悉的关键词,所以那个答案对我来说无法阅读......尽管如此,这并不是一个重复的问题,只是在同一个主题内的一个问题,可能有一个有用的答案。 - Riptyde4
1
也许阅读这个答案会更容易理解:https://dev59.com/b3M_5IYBdhLWcg3wq1CF#19014644 - Bryan Chen
4个回答

469

nullptr 的类型是 std::nullptr_t。它可以隐式转换为任何指针类型。因此,在重载决议中,它将匹配 std::nullptr_t 或指针类型,但不会匹配其它类型,例如 int

0(也就是 C 中的 NULL 被引入到 C++ 中)可能会在重载函数解析时导致歧义等问题:

f(int);
f(foo *);

(感谢Caleth在评论中指出这一点。)


26
@Cheersandhth.-Alf 我不知道该如何回应这个问题,除了我知道自己在问什么以及这是最易懂的解释之外。请问还有其他需要翻译的内容吗? - Riptyde4
11
@Riptyde4:我认为Shafik的回答是最全面的。引用中包含了这个回答的“多义性重载”和我的回答中的“模板参数类型问题”,而且它还是一个很好的参考资料。这个回答只是原因的一小部分。 - Cheers and hth. - Alf
2
但是我们总是可以使用类型转换运算符来指定类型,例如 f((int) NULL) 或 f((foo*) NULL),作为解决歧义的替代方法... 对吗? - Arjun
7
吹毛求疵:nullptr 的类型为 std::nullptr_t,它不是指针类型。nullptr 可以隐式地转换为任何指针类型,而且重要的是 不会 转换为任何整数类型。 - Caleth
谢谢,Caleth。你是正确的。我已经调整了我的措辞。 - Joe Z
显示剩余3条评论

97
您可以阅读一个名字的空指针:nullptr来找到为什么它被替换的好解释,引用该论文的话说:

这个问题属于以下类别:

  • 通过提供一种用户编写更少歧义代码的方式来改善库构建支持,以便随着时间的推移,库编写者不需要担心整数和指针类型的重载。

  • 通过使表达整数0和nullptr变得明确易懂来改善通用编程的支持。

  • 使C++更易于教学和学习。


65

这里是Bjarne Stroustrup的话,

C++中,NULL的定义是0,因此只有美学上的区别。我更喜欢避免使用宏,所以我使用0。另一个问题是人们有时错误地认为NULL与0不同和/或不是整数。在早期标准之前的代码中,NULL有时被定义为不合适的东西,因此必须避免使用。现在这种情况已经不太常见了。

如果你必须给null指针命名,请称其为nullptr;这就是C++11中的名称。然后,“nullptr”将成为关键字。


9
这并没有真正回答这个问题,只是提供了一个名称来源的来源... - Sinkingpoint
9
@Quirliom:我认为这就是C++11中引入新关键字nullptr的原因。 - Deidrei
3
@Sinkingpoint 是正确的。这是部分回答,因为它解释了 NULL 的一个问题,但它并没有解释 nullptr 如何避免这个问题,或者为什么实际上引入了 nullptr(这些才是 OP 实际上在问的问题)。 - Pharap
好的,谢谢。但是很抱歉,因为我很久之前回答过这个问题,现在我记不清楚了。 - Deidrei

18

一个原因是:字面上的0很容易取得类型int,例如在完美参数转发或更一般地作为带有模板类型的参数中。

另一个原因是:代码的可读性和清晰度。


我同意,但是:起源问题是关于NULL和nullptr的区别;-) - hfrmobile
4
@hrfmobile:NULL 是一个宏,通常被定义为文字 0(可能带有类型后缀)。在当前的 g++ 版本 9.2 中,它被定义为内部变量 __null。在当前的 Visual C++ 2019 中,它被定义为普通的 0。因此,我给出的第一个理由适用于NULL被定义为文字的情况。第二个原因总是适用的,但更具主观性。然而,大多数人都认为全大写字母很丑陋,尖叫。这就是为什么宏使用这种命名约定的主要原因。 - Cheers and hth. - Alf
3
对于NULL类型,C++标准本可以添加std::nullptr_t而不是添加nullptr,并定义#define NULL ((std::nullptr_t) 0),类似于POSIX在C中所做的:#define NULL ((void *) 0)。这样就不需要新的关键字了。 - alx - recommends codidact
2
@alx,我猜关键字的使用排除了过于普遍的 #undef NULL / #define NULL <something else I think is even better than the standard>,这可能会让查看代码中的 NULL 的人误以为它意味着一件事情,而实际上它意味着另一件事情。毕竟,#define true ((bool)1) 有什么问题呢? - kbro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接