我目前正在阅读一本关于C ++的书,作者在其中解释说最好使用常量而不是NULL
宏,但没有详细说明原因或给出任何优缺点。
那么为什么最好使用常量:
const int NULL = 0;
int *ptr = NULL;
改为:
int *ptr = NULL;
唯一的解释是NULL
宏不具有类型安全性。我目前正在阅读一本关于C ++的书,作者在其中解释说最好使用常量而不是NULL
宏,但没有详细说明原因或给出任何优缺点。
那么为什么最好使用常量:
const int NULL = 0;
int *ptr = NULL;
改为:
int *ptr = NULL;
唯一的解释是NULL
宏不具有类型安全性。所有内容都已过时。
使用nullptr
代替。它是指向任何东西的指针的特殊值,甚至还有自己的类型,std::nullptr_t
。
不能保证地址0x0对应于“未初始化”的指针值,但请注意,字面量0保证转换为空指针值。
0
仍然保证会隐式转换为一个空指针。 - user743382ptr=0;
会将指针ptr
赋予平台适当的空值。 - Chris Beckeconst int
全局对象并不是,即使它使用字面值 0
进行初始化也不是)。 - The Paramagnetic Croissantnullptr
而不是NULL。#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
这样的东西有一个类型(它是因为其他原因而丑陋)。只有宏参数可能会有问题。 - MikeMB事实上,“NULL宏”不具备类型安全性。这意味着您的编译器不知道您是否使用了正确的类型。例如,在使用memcpy
时:
SomeClass a;
AnotherClass b;
memcpy((void*)&a, (void*)&b, sizeof(b));
(摘自这里)
编译器只在内存中看到两个指针。但是SomeClass
和AnotherClass
都是不完整的类型。
正如其他人所说,如果您可以使用C++11,只需使用nullptr
即可。
NULL
无关,而是与不安全的void*
通用指针类型有关。此外,在C++中使用memcpy
通常不是一个好主意。 - Some programmer dude
NULL
宏首先必须是一个宏。其次,它可以是被评估为零的常量右值、实际上的零或其他特定于平台的值,当转换为指针时为 null 指针,或者它可以是nullptr_t
prvalue(像nullptr
)。该宏通常定义为0
或nullptr
(取决于编译器使用的 C++ 规范)。使用变量没有意义,也会导致转换问题。 - Some programmer dude