NULL 宏实际上可以是 nullptr 吗?

Can the NULL macro actually be a nullptr?

根据标准N4713(7.11/1)草案:

A null pointer constant is an integer literal (5.13.2) with value zero or a prvalue of type std::nullptr_t.

和 21.2.3/2:

The macro NULL is an implementation-defined null pointer constant.

按照NULL可以定义为nullptrcppreference:

中也提到了同样的内容
#define NULL 0
//since C++11
#define NULL nullptr

同时"Additive operators"子句说(8.5.6/7):

If the value 0 is added to or subtracted from a null pointer value, the result is a null pointer value. If two null pointer values are subtracted, the result compares equal to the value 0 converted to the type std::ptrdiff_t.

因此下面的代码应该是有效的:

0 + nullptr; 
nullptr - nullptr; 

但由于缺少 std::nullptr_t 的 +/- 运算符,code is invalid.

有什么我没有考虑到的,或者 NULL 宏实际上不能定义为 nullptr 吗?

虽然nullptr是空指针常量,但它不是空指针。后者是一些指针类型的值,std::nullptr_t 不是。

参考:

A null pointer constant is an integer literal (5.13.2) with value zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type. Such a conversion is called a null pointer conversion. [...]

7.11/1 in N4659,强调我的

所以 NULL 确实可以 nullptr 而无需提供算术运算符。

关键字nullptr表示指针字面量。它是 std::nullptr_t 类型的 prvalue。存在从 nullptr 到任何指针类型的空指针值和任何指向成员类型的指针的隐式转换。 nullptr 本身既不是指针值也不是指针。因此算术运算不适用于nullptr.

nullptr是空指针字面量,虽然nullptr转为指针类型的结果是空指针值,但nullptr本身并不是指针类型,但类型为 std::nullptr_t。如果您将 nullptr 转换为指针类型,则该算法有效:

0 + (int*)nullptr; 
(int*)nullptr - (int*)nullptr;

Can the NULL macro actually be a nullptr?

是的,因为 nullptr 是空指针文字。

请注意,在 C++11 之前,C++ 中的所有空指针文字恰好也是整数文字,所以这个糟糕的代码:char c = NULL; 曾经在实践中起作用。如果 NULL 定义为 nullptr,则该代码不再有效。

For addition, either both operands shall have arithmetic or unscoped enumeration type, or one operand shall be a pointer to a completely-defined object type and the other shall have integral or unscoped enumeration type.

For subtraction, one of the following shall hold:
(2.1) both operands have arithmetic or unscoped enumeration type; or
(2.2) both operands are pointers to cv-qualified or cv-unqualified versions of the same completely-defined object type; or
(2.3) the left operand is a pointer to a completely-defined object type and the right operand has integral or unscoped enumeration type.

std::nullptr_t 是其中的 none,因此 std::nullptr 无法参与加法运算。

注意,并不是所有的指针值都可以参与。例如,函数指针值和 void 指针值不能,即使它们都可以是空指针值。