36

我有以下代码:

MyType x = NULL;

NetBeans 给了我一个建议,将其更改为:

MyType x = __null;

我查了一下,发现它__null被称为“编译器关键字”,我认为这意味着它在编译器内部使用。我不明白为什么 NetBeans 建议将其更改为编译器关键字。

NULLc++和c++有什么区别__null

4

3 回答 3

54

__null是一个g++内部事物,其用途与 C++11 中添加的标准大致相同nullptr(始终充当指针,而不是整数)。

NULL被定义为0,它可以隐式地用作整数、布尔值、浮点值或指针,当您想调用专门采用指针的函数时,这在重载解析时是一个问题。

无论如何,您都不应该使用它,__null因为它是一个g++实现细节,因此使用它可以保证代码不可移植。如果您可以依赖 C++11(现在肯定可以吗?),请使用nullptr. 如果没有,NULL这是您唯一的便携式选择。

于 2018-12-28T19:54:55.933 回答
11

NULL已经从 C 取代到 C++ 并且 - 在 C++11 之前 - 采用了它的 C 含义:

直到 C++11:宏 NULL 是实现定义的空指针常量,它可以是整数类型的整数常量表达式右值,其计算结果为零。

然后,C++11 引入了一个专用的空指针字面nullptr量类型std::nullptr_t。但是 - 可能是为了向后兼容 - 宏NULL没有被删除;它的定义稍微宽松一点,因为编译器现在可以将其定义为整数或指针类型:

C++11 及以上:值为 0 的整数文字,或 std::nullptr_t 类型的纯右值

如果您使用NULL,那么您将在重载决议中获得实现定义的行为。例如,考虑以下代码,其编译器使用NULL-macro 的整数版本。然后使用NULLas 参数传递给函数的调用可能会导致歧义:

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相比之下,它非常便携。

于 2018-12-28T20:23:00.640 回答
8

NULL是空指针的旧 C 符号。C++ 传统上用于0空指针,并且自 C++11 标准nullptr.

考虑到这x似乎不是一个指针,那么你不能初始化x为一个空指针,并且该__null符号可能是空的一些编译器内部符号(这是一个在标准 C++ 中并不真正存在的概念)。

如果要x初始化为某个默认状态,则必须依靠MyClass默认构造函数将对象及其成员变量初始化为一些合适的默认值。

于 2018-12-28T19:56:47.067 回答