我有以下代码:
MyType x = NULL;
NetBeans给了我一个建议,把它改成这样:
MyType x = __null;
我查了一下,发现__null
被称为"编译器关键字",我认为这意味着它在编译器内部使用。我不明白为什么NetBeans建议将其更改为编译器关键字。
c++中的NULL
和__null
有什么区别?
__null
是一个g++
内部事物,其作用与C++11中添加的标准nullptr
大致相同(始终充当指针,而不是整数)。
NULL
被定义为0
,它可以隐式地用作整数、布尔值、浮点值或指针,这在重载解析方面是个问题,当你想调用专门使用指针的函数时。
无论如何,您都不应该使用__null
,因为它是g++
实现细节,所以使用它可以保证代码不可移植。如果您可以依赖C++11(现在肯定可以了吗?),请使用nullptr
。如果没有,NULL
是您唯一的可移植选项。
NULL
已经从C取代为C++,并且在C++11之前采用了其C的含义:
直到C++11:宏NULL是一个实现定义的NULL指针常数,它可以是计算结果为零的integer类型。
C++11随后引入了类型为std::nullptr_t
的专用空指针文字nullptr
。但是,可能是为了向后兼容,宏NULL
没有被删除;它的定义有点宽松,因为编译器现在可以将它定义为积分或指针类型:
C++11以后:值为零的整数文字,或prvalue为类型std::nullptr_t
如果使用NULL
,则在重载解析中获得实现定义的行为。例如,考虑以下代码和使用NULL
-宏的集成版本的编译器。然后,使用NULL
作为传递给函数的参数的调用可能会导致歧义:
struct SomeOverload {
SomeOverload(int x) {
cout << "taking int param: " << x << endl;
}
SomeOverload(void* x) {
cout << "taking void* param: " << x << endl;
}
};
int main() {
int someVal = 10;
SomeOverload a(0);
SomeOverload b(&someVal);
// SomeOverload c(NULL); // Call to constructor is ambiuous
SomeOverload d(nullptr);
}
因此,建议在任何想要表达指针类型的地方使用nullptr
。
不要使用__null
,因为这是编译器特定的、不可移植的常量;相比之下,nullptr
是非常便携的。
NULL
是空指针的旧C符号。C++传统上使用0
作为空指针,并且自从C++11标准nullptr
。
考虑到x
似乎不是指针,那么就不能将x
初始化为空指针,而__null
符号可能是空值的编译器内部符号(这在标准C++中并不存在)。
如果希望x
初始化为某个默认状态,则必须依赖MyClass
默认构造函数将对象及其成员变量初始化为一些合适的默认值。