考虑代码
#include <iostream>
void foo(int* p)
{
std::cout << "pointer" << 'n';
}
void foo(int p)
{
std::cout << "value" << 'n';
}
int main()
{
foo( 0 ); // value
foo( NULL ); // error: call of overloaded ‘foo(NULL)’ is ambiguous foo( NULL );
return 0;
}
在这里,我们可以看到为空指针选择正确的重载的问题,这可以通过将nullptr
传递给函数foo
的第二次调用来解决,但我的问题是关于不同的东西......
据我所知,大多数实现将NULL
定义为一个常量文字0
,例如 (#define NULL 0
(,因此在编译时预计第二次调用如下所示 - foo( 0 )
,
但是预处理器给出了一些奇怪的输出(运行g++ -std=c++11 -E main.cpp -o main
后(
int main()
{
foo( 0 );
foo(
# 25 "main.cpp" 3 4
__null
# 25 "main.cpp"
);
return 0;
}
这里__null
是什么?
这是一个内置的int类型吗?
__null
是一个内置的编译器。 GCC 使用它来提供更好的诊断。 问题是你真的想NULL
定义为
#define NULL ((void *) 0)
— 就像在 C 中一样。 但是使用当前C++,您将无法编写
int *p = NULL;
因为与 C 不同,没有从 void *
到其他指针类型的隐含转换。 因此,GCC 将__null
实现为魔术空指针常量,该常量对任何指针类型都有效,但不是整数。 因此,GCC 可以发出警告
int a = NULL;
否则这是不可能的。
从本质上讲,__null
是nullptr
的早期版本,但它更保守,因为它只是一个扩展,而不是语言的改变。