思维导图
1.C++98的指针空值
一般我们在声明一个变量时,最好给变量一个合适的初始化值,否则可能会出现不可预测的错误。而我们一般是按照如下方法初始化的:
int main()
{
int a = 0;
int b = NULL;
//...
}
NULL实际是一个宏,我们在C头文件(stddef.h)中,可以看到如下代码:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0 //被定义为常量0
#else
#define NULL ((void *)0) //或者被定义为无类型指针(void*)
#endif #endif
从头文件我们可以看出,NULL被定义为了常量0或者被定义为了无类型指针(void*)。
但是因为NULL存在二义性,所以会出现如下的错误情况
void fun(int)
{
cout << "f(int)" << endl;
}
void fun(int*)
{
cout << "f(int*)" << endl;
}
int main()
{
fun(0);
fun(NULL);//本意是调用第二个函数
fun((int*)NULL);
system("pause");
return 0;
}
程序本意是享用fun(NULL)调用指针版本的(int*)函数,但是由于NULL被定义为0,所以与程序的初衷不同
总结
在C++98中,常量0即可以是一个整形数字,又可以是无类型的指针(void*)常量,但是编译器默认情况下将其看作一个整型常量,如果像按照指针方式来使用,需要强行转换为(void*)。
2.nullptr
为了考虑兼容性,C++11并没有消除常量0的二义性,C++11给出了全新的nullptr作为空指针。
为什么C++11不对NULL做拓展呢?
- 1.NULL之前本来就是一个宏。
- 2.不同的编译器厂商可能对NULL实现不太相同,可能会影响旧的程序。
为了避免混杂,C++提供了nullptr:代表一个指针常量。
nullptr是有类型的,其类型为nullptr_t,仅仅可以被隐式类型转换为指针类型,nullptr在头文件被定义为:
typedef decltype(nullptr) nullptr_t;
注意:
1.在使用nullptr表示空指针时,不需要包头文件,因为在C++11中他是以关键字存在的。
2.在C++11时,sizeof(nullptr)和sizeof((void*)0)所占字节相同,都为4。
3.为了提高代码的健壮性,后续表示指针空值时最好使用nullptr。