c++之nullptr与NULL

NULL的本质

在c++中,NULL的定义可能是以下几种形式之一:

#define NULL 0
#define NULL ((void*)0)

nullptr的本质

nullptr是c++11Y引入的关键字,它是std::nullptr_t类型的右值常量。

  • nullptr可以隐式转换为任何指针类型
  • nullptr不能隐式转换为整型

调用NULL为什么会产生歧义

假设有下面的代码:

void foo(int);
void foo(char*);

foo(NULL); //这个调用会调用哪个函数呢?

上面的调用会发生什么呢?

答案:编译报错,编译器编译foo(NULL)时会发生歧义,原因如下:

1.如果NULL被定义为0:

  • 0可以转换为int类型(精确匹配)
  • 0也可以转换为char*类型
  • 两个转换路径都是可能的,所以会发生歧义

2.即使NULL被定义为((void*)0):

  • void*可以转换为char*
  • void*也可以转换为整型
  • 仍然存在歧义

为什么nullptr不会发生歧义?

同样的例子:

void foo(int);
void foo(char*);

foo(nullptr);  //正确,明确调用foo(char*)

为什么这个不会报错呢?原因如下:

  • nullptr是std::nullptr_t类型
  • std::nullptr_t可以隐式转换为任何类型
  • std::nullptr_t不能转换为整型
  • 因此只有foo(char*)是调用项

说白了就是,如果使用NULL,那么在某些情况下可能会编译报错,因为编译器编译时遇到了歧义,不知道使用哪个匹配的函数。

建议

  1. 在c++中永远使用nullptr,而不是NULL
  2. 在新代码中完全避免使用NULL