一、引入
在C语言中,我们经常使用 NULL 来表示空指针,但是在C++中,我们发现既有 nullptr,又有 NULL 。只看英文的话,好像都是空指针的意思。那么到底是怎么一回事呢?
二、C++对 NULL 的定义
在 C++98标准和 C++03标准中,还没有 nullptr ,只有 NULL 。那么在 C++中,NULL是如何定义的?
来看看编译器提供的头文件是怎么说的:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
通过上面的代码,我们发现在 C++中,NULL 被定义为整形常量 0(而在 C 中,NULL被定义为无类型指针常量 (void*) 0 )。
也就是说在 C++中,下面的这两行代码是完全等价的,没有区别。
int* p1 = NULL;
int* p2 = 0;
三、C++中 NULL 的问题
其实 C++把 NULL 定义为 0 来表示空指针在大多数情形下不会有问题,因为 0 可以指地址编号为0的地址。
但是 NULL 作为参数在函数重载中的运行结果与我们的期望不符:
void test(int)
{
cout << "test(int)" << endl;
}
void test(int*)
{
cout << "test(int*)" << endl;
}
int main()
{
test(0);
test(NULL);
return 0;
}
我们本以为 test(NULL) 会调用 test(int*) 这个函数,但实际上 test(NULL) 和 test(0) 调用的函数都是 test(int) 。
为什么会这样呢?
这是因为在 C++中,字面常量 0 既可以表示一个整形常量 0,也可以表示无类型指针常量 (void*) 0,但是编译器默认把它看成是一个整形常量 0 (如果把 0 当指针使用,就必须对其进行强转 (void*) 0 )。
由于 NULL 被定义为 0,编译器默认 NULL 就是整形常量 0,所以 test(NULL) 调用 test(int) 函数,而非 test(int*) 函数。
四、C++11标准的新增关键字 nullptr
为了解决这个问题,C++11标准增加了新的关键字 nullptr,保证在任何情况下都表示空指针。
让我们用上面的代码给 0 、NULL 和 nullptr 做个对比:
void test(int)
{
cout << "test(int)" << endl;
}
void test(int*)
{
cout << "test(int*)" << endl;
}
int main()
{
test(0);
test(NULL);
test(nullptr);
return 0;
}
因此,在 C++11标准出来以后,不推荐使用 NULL 来代表空指针。为了提高代码的健壮性,建议以后表示指针空值时最好都使用 nullptr 。