我目前正在阅读一本关于C ++的书,在本书中,作者解释说使用常量而不是NULL
宏更好,但没有真正解释为什么或给出任何优点或缺点。
为什么使用它会更好:
const int NULL = 0;
int *ptr = NULL;
而不是:
int *ptr = NULL;
唯一的解释是NULL
宏不是类型安全的。
答案 0 :(得分:38)
一切都过时了。
请改用nullptr
。对于没有指向任何东西的指针,这是一个特殊值。它甚至有自己的类型,std::nullptr_t
。
无法保证地址0x0对应于"未初始化的"指针值,但请注意,文字0保证转换为空指针值。
答案 1 :(得分:22)
如果您使用的是C ++ 11,那么建议使用nullptr
而不是NULL。
以下是 Bjarne Stroustrup的C ++编程语言
的几行
- 在较旧的代码中,通常使用0或NULL而不是nullptr(第7.2.2节)。但是,使用nullptr可以消除整数(如0或NULL)和指针(如nullptr)之间的混淆。
- 在不同的实现中,NULL的定义存在差异;例如,NULL可能是0或0L。在C中,NULL通常是(void *)0,这使得它在C ++(第7.2.1节)中是非法的:
- 使用nullptr使代码比替代方案更具可读性,并避免在函数重载以接受指针或整数时可能出现的混淆
我希望这会帮助你理解。
答案 2 :(得分:1)
作者是正确的,没有输入预处理器宏(与例如变量相反,在声明期间强制执行输入)。因此宏在这方面更危险,因为编译器无法验证表达式中的类型正确性,并且在编译期间可能会遗漏一条重要的警告/错误消息
当然,编译器创建者可以(并且通常会,我希望)提供一个NULL宏版本,该宏版本扩展为具有强制转换的值,与C定义相同(不相同!):
#define N ((void*)0)
BTW:因为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
答案 3 :(得分:0)
确实," NULL宏"不是类型安全的。这意味着您的编译器不知道您是否使用了正确的类型。例如,使用memcpy
时:
SomeClass a;
AnotherClass b;
memcpy((void*)&a, (void*)&b, sizeof(b));
(摘自there)
编译器只在内存中看到两个指针。但SomeClass
和AnotherClass
是不完整的类型。
正如其他人所说,如果您可以使用C ++ 11,只需使用nullptr
。