1.为什么引入nullptr?
在实际开发中,避免产生“野指针”最有效的方法就是在定义指针时完成初始化操作,即定义为空指针。
野指针是指没有明确指向的指针。野指针往往指向的是那些不可用的内存区域,这意味着像操作普通指针那样使用野指针(如&p),可能会导致程序异常。
C++98/03标准中,将一个指针初始化为空指针方式有两种:
(1)指针初始化为0这个内存空间。
int *p = 0;
明确了指针的指向,并且大部分操作系统不允许用户对地址为0的内存空间执行操作。
(2)指针初始化为NULL。(常用)
int *p = NULL
我们一般采用这种方式初始化。NULL是C++事先定义好的一个宏,其值为字面量0(#define NULL 0)。
使用第二种方式初始化能满足大部分场景需要,但在个别情况下会导致程序运行不符合预期。例如:
#include <iostream>
using namespace std;
void isnull(void *c){cout << "void*c" << endl;
}
void isnull(int n){cout << "int n" << endl;
}
int main() {isnull(0);isnull(NULL);return 0;
}
程序执行结果为:
int n
int n
对于 isnull(0) 来说,它调用的是isnull(int n) 函数;而对于 isnull(NULL),我们期望它调用的是 isnull(void*c) 函数,但观察程序的执行结果不难看出,与我们的预期不符合。
若想正确调用isnull(void *c)函数,需要在调用中进行强制类型转换,如下所示:
isnull((void*) NULL );
只有这样才能成功调用到预期的函数。(可以编译观察结果)。
C++98标准使用期间,NULL得到了广泛应用,出于兼容性考虑,C++11对NULL没做任何改变,但为了解决这个问题,C++11标准引入了一个新的关键字——nullptr。(本文的主角)
2.nullptr介绍
nullptr是nullptr_t类型(C++11新增加的数据类型,称为“指针空值类型”)的右值常量,专门用于初始化空指针。nullptr就是该类型的一个实例对象(帮你定义好了,可以直接用),我们也可以自己定义出完全相同的nullptr实例对象。
3.nullptr用法
初始化指针。
特点:可以被隐式转换成任意的指针类型,但不能转换为整数类型(解决了上面函数的调用问题)。
int * a1 = nullptr;
char * a2 = nullptr;
double * a3 = nullptr;
4.与NULL的区别
(1)nullptr具有明确的类型nullptr_t。
(2)nullptr可以隐式转换成任意类型的指针,但不能转化为整数类型。而NULL本质上还是一个整数(0)。
5.总结
nullptr主要用于指针初始化和指针比较(判断指针是否为空)。具有安全和语义清晰的优点。但在使用中,要注意版本和兼容性,在新的代码中建议优先使用nullptr使代码更加健壮。