根据标准N4713(7.11/1)的草案:
空指针常量是值为零或 prvalue 为
std::nullptr_t
的整数文本 (5.13.2)。
和 21.2.3/2:
宏
NULL
是实现定义的空指针常量。
因此,NULL
可以定义为nullptr
。在 cpp 首选项中也提到了同样的内容:
#define NULL 0
//since C++11
#define NULL nullptr
同时,"加法运算符"条款说(8.5.6/7):
如果将值
0
添加到空指针值或从空指针值中减去,则结果为空指针值。如果两个空 指针值被减去,结果等于值0
转换为类型std::ptrdiff_t
。
因此,以下代码应该是有效的:
0 + nullptr;
nullptr - nullptr;
但由于缺少用于std::nullptr_t
的 +/- 运算符,代码无效。
是否有我没有考虑NULL
或者宏实际上无法定义为nullptr
?
虽然nullptr
是空指针常量,但它不是空指针值。后者是某种指针类型的值,std::nullptr_t
不是。
参考:
空指针常量是值为零或 prvalue 类型为
std::nullptr_t
的整数文本 (5.13.2)。空指针常量可以转换为指针类型;结果是该类型的空指针值,并且 可与对象指针或函数指针类型的所有其他值区分开来。这种转换称为 空指针转换。[...]
7.11/1 in N4659,强调我的
因此,NULL
确实可以在不提供算术运算符的情况下nullptr
。
nullptr
是空指针文本,尽管将nullptr
转换为指针类型的结果是空指针值,但nullptr
本身不是指针类型,而是std::nullptr_t
类型。如果将nullptr
转换为指针类型,则算术有效:
0 + (int*)nullptr;
(int*)nullptr - (int*)nullptr;
空宏实际上可以是一个空点吗?
是的,因为nullptr
是空指针文本。
请注意,在 C++11 之前,C++中的所有空指针文本恰好也是整数文本,因此这个糟糕的代码:char c = NULL;
在实践中起作用。如果NULL
定义为nullptr
,则该代码不再有效。
关键字nullptr
表示指针文本。它是std::nullptr_t
型prvalue
.存在从任何指针类型的nullptr
到 null 指针值的隐式转换以及任何指向成员类型的指针。nullptr
本身既不是指针值,也不是指针。因此算术运算不适用于nullptr
。
对于加法,两个操作数都应具有算术或无作用域枚举类型,或者一个操作数应是指向完全定义的对象类型的指针,另一个操作数应具有整数或无作用域枚举类型。
对于减法,应保持以下条件之一:
(2.1) 两个操作数都有算术或无作用域枚举类型; or
(2.2) 两个操作数都是指向同一完全定义的对象类型的 CV 限定版本或 CV 非限定版本的指针; or
(2.3) 左操作数是指向完全定义的对象类型的指针,右操作数具有整数或无作用域枚举类型。
std::nullptr_t
不是这些,因此std::nullptr
不能参与增材操作。
请注意,甚至并非所有指针值都可以参与。例如,函数指针值和 void 指针值不能,即使两者都可以是空指针值。