快捷搜索: 王者荣耀 脱发

浅谈 C++中的 NULL 和 nullptr

一、引入

在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 。

经验分享 程序员 微信小程序 职场和发展