我们现在拥有许多新功能的C 11 . 一个有趣且令人困惑的(至少对我而言)是新的 nullptr
.
嗯,不再需要令人讨厌的宏 NULL
.
int* x = nullptr;
myclass* obj = nullptr;
不过,我还没有得到 nullptr
的工作方式 . 例如,Wikipedia article说:
C 11通过引入一个新关键字作为区分空指针常量来解决这个问题:nullptr . 它的类型为nullptr_t,它是可隐式转换的,可与任何指针类型或指向成员类型的类型相媲美 . 除了bool之外,它不可隐式转换或与整数类型相比 .
它是一个关键字和一个类型的实例?
另外,你有另一个例子(在维基百科旁边),其中 nullptr
优于好老 0
?
11 回答
好吧,其他语言保留了类型实例的单词 . 例如,Python:
这实际上是一个相当接近的比较,因为
None
通常用于尚未初始化的东西,但同时比较如None == 0
是假的 .另一方面,在普通C中,
NULL == 0
将返回真正的IIRC,因为NULL
只是一个返回0的宏,它总是一个无效的地址(AFAIK) .这并不奇怪 .
true
和false
都是关键字,而文字则是一个类型(bool
) .nullptr
是std::nullptr_t
类型的指针文字,它是一个prvalue(你不能使用&
获取它的地址) .关于指针转换的
4.10
表示std::nullptr_t
类型的prvalue是一个空指针常量,并且一个整数空指针常量可以转换为std::nullptr_t
. 不允许相反的方向 . 这允许为指针和整数重载函数,并传递nullptr
以选择指针版本 . 传递NULL
或0
会令人困惑地选择int
版本 .nullptr_t
到整数类型的强制类型需要reinterpret_cast
,并且具有与(void*)0
的强制类型相同的语义到整数类型(映射实现定义) .reinterpret_cast
无法将nullptr_t
转换为任何指针类型 . 如果可能,请依靠隐式转换或使用static_cast
.标准要求
sizeof(nullptr_t)
为sizeof(void*)
.来自nullptr: A Type-safe and Clear-Cut Null Pointer:
其他参考:
WikiBooks,带有示例代码 .
Stack Overflow:Do you use NULL or 0 (zero) for pointers in C++?
template
Google群组:comp.lang.c++.moderated - compiler discussion
当你有一个可以接收指向多个类型的指针的函数时,用
NULL
调用它是不明确的 . 现在解决这个问题的方法是非常hacky接受一个int并假设它是NULL
.在
C++11
中,您将能够在nullptr_t
上重载,以便ptr<T> p(42);
将是编译时错误而不是运行时assert
.为什么C 11中的nullptr?它是什么?为什么NULL不够?
C专家Alex Allain says it perfectly here:
“...想象你有以下两个函数声明:
Although it looks like the second function will be called--you are, after all, passing in what seems to be a pointer--it's really the first function that will be called! The trouble is that because NULL is 0, and 0 is an integer, the first version of func will be called instead. 这是一种事情,是的,不知道发生了什么的细节,它可能看起来像编译器错误 . A language feature that looks like a compiler bug is, well, not something you want.
Enter nullptr. In C++11, nullptr is a new keyword that can (and should!) be used to represent NULL pointers; 换句话说,无论你以前写过NULL,都应该使用nullptr . It's no more clear to you, the programmer ,(每个人都知道NULL意味着什么), but it's more explicit to the compiler ,当用作指针时,它将不再看到任何地方被用来具有特殊含义 .
nullptr
不能分配给integral type
,例如int,但只能分配pointer
;内置指针类型(如int *ptr
)或智能指针(如std::shared_ptr<T>
)我相信这是一个重要的区别,因为
NULL
仍然可以分配给integral type
和pointer
,因为NULL
是一个扩展为0
的宏,它既可以作为int
的初始值,也可以作为pointer
.是 . 它也是我们的 生产环境 代码中出现的(简化的)现实世界的例子 . 它只是突出,因为gcc能够在交叉编译到具有不同寄存器宽度的平台时发出警告(仍然不确定为什么只有当从x86_64交叉编译到x86时,警告
warning: converting to non-pointer type 'int' from NULL
):考虑这段代码(C 03):
它产生这个输出:
它是一个关键字,因为标准将指定它 . ;-)根据最新消息公共草案(n2914)
它很有用,因为它不会隐式转换为整数值 .
假设你有一个函数(f),它被重载以获取int和char * . 在C 11之前,如果你想用空指针调用它,并且你使用NULL(即值0),那么你将调用为int重载的那个:
这可能不是你想要的 . C 11用nullptr解决了这个问题;现在您可以编写以下内容:
0曾经是唯一可以用作指针的无转换初始化器的整数值:你不能在没有强制转换的情况下用其他整数值初始化指针 . 您可以将0视为consexpr singleton,在语法上类似于整数文字 . 它可以启动任何指针或整数 . 但令人惊讶的是,你会发现它没有明显的类型:它是
int
. 那么为什么0可以初始化指针而1不能?一个实际的答案是我们需要一种定义指针空值的方法,并且int
直接隐式转换为指针容易出错 . 因此,在史前时代,0变成了一个真正怪异的怪兽 .nullptr
被提议为初始化指针的空值的真实单例constexpr表示 . 它不能用于直接初始化整数并消除以0表示定义NULL
所涉及的歧义 . 可以使用std语法将_1772389定义为库,但在语义上看起来是缺少的核心组件 .NULL
现已弃用,而不是nullptr
,除非某些库决定将其定义为nullptr
.NULL不必为0.只要使用始终为NULL且永远不为0,NULL可以是任何值 . 假设您使用平坦内存对von Neuman微控制器进行编程,其中断vektors为0.如果NULL为0且某些内容写入NULL指针,则微控制器崩溃 . 如果允许NULL为1024而在1024处有一个保留变量,则写入不会使其崩溃,您可以从程序内部检测NULL指针赋值 . 这在PC上是无意义的,但对于太空探测器,军事或医疗设备而言,重要的是不要崩溃 .