NULL 宏或 NULL 常量

NULL macro or NULL const

我目前正在阅读一本关于 C++ 的书,在这本书中,作者解释说使用常量比 NULL 宏更好,但没有真正解释原因或给出任何优点或缺点。

那么为什么最好使用:

const int NULL = 0;
int *ptr = NULL;

而不是:

int *ptr = NULL;

给出的唯一解释是 NULL 宏不是类型安全的。

都过时了。

改用nullptr。这是一个不指向任何东西的指针的特殊值。它甚至有自己的 type, std::nullptr_t.

不能保证地址 0x0 对应于 "uninitialised" 指针值,但请注意,文字 0 一定会转换为空指针值。

作者没有输入预处理器宏是正确的(与例如变量相反,变量在声明期间强制输入)。所以宏在这方面更危险,因为编译器无法验证表达式中的类型正确性,你可能会在编译期间错过重要的 warning/error 消息

当然,编译器创建者可以(我希望通常会这样做)提供一个 NULL 宏的版本,它扩展为一个带有强制转换的值,等效于(不完全相同!)C 定义:

#define N ((void*)0)

顺便说一句:因为 C++11 NULL 可以评估为 std::nullptr_t 类型。

所以我不希望 NULL 有太多问题,但你可以考虑避免使用你自己的宏。或者至少谨慎使用宏,只要您不能完全确定您可以预见您的宏可能恰好在各种表达式中展开的许多上下文。

作为一个简短的练习,您可以尝试下面的操作,看看宏没有类型,因此它们的类型在表达式中被推导出来,例如算术转换或促销。在下面的示例中,MY_NULL 宏(=没有转换)导致非常危险的分配。这就是你的书作者的想法,并试图警告你。

MY_TYPED 宏计算为强制转换的表达式,这确保编译器在尝试时捕获错误,例如i = MY_TYPED_NULL;

#define MY_NULL 0
#define MY_TYPED_NULL ((void*)0)
int i;
float f;
void* v;
i = MY_NULL;    // bad: no compiler error
f = MY_NULL;    // bad: no compiler error
v = MY_NULL;    // seems to match programmer's intention
i = MY_TYPED_NULL;    // good: compiler error
f = MY_TYPED_NULL;    // good: compiler error
v = MY_TYPED_NULL;    // correct

确实,"NULL macro" 不是类型安全的。这意味着您的编译器不知道您是否使用了正确的类型。例如,当使用 memcpy:

SomeClass a;
AnotherClass b;
memcpy((void*)&a, (void*)&b, sizeof(b));

(取自there

编译器在内存中只看到两个指针。但是 SomeClassAnotherClass 是不完整的类型。

正如其他人所说,如果你可以使用C++11,就使用nullptr

如果您使用的是 C++11,那么建议使用 nullptr 而不是 NULL。

下面是 Bjarne Stroustrup

C++ 编程语言中的几行
  • In older code, 0 or NULL is typically used instead of nullptr (§7.2.2). However, using nullptr eliminates potential confusion between integers (such as 0 or NULL) and pointers (such as nullptr).
  • there are differences in the definition of NULL in different implementations; for example, NULL might be 0 or 0L. In C, NULL is typically (void∗)0, which makes it illegal in C++ (§7.2.1):
  • Using nullptr makes code more readable than alternatives and avoids potential confusion when a function is overloaded to accept either a pointer or an integer

希望以上内容能帮助您理解。