C++里怎么样表示空指针

时间:2022-08-29 21:27:45

  在C++11(C++0x)里,空指针有了一个官方版的表示:nullptr。在此之前C++里的空指针应该怎么表示呢?

  一种方法是定义一个NULL宏(#define NULL 0)来表示空指针,虽然本质上和直接写成0一样,但NULL能相对直观地表示这是个指针。

  一些知名头文件里就带有NULL的定义,比如windows.h和stdio.h。直接用NULL似乎是个不错的主意。

  有时候源文件中并不需要引用到这些知名头文件,那么NULL就要由自己来定义。这样,可能在很多地方都充斥着NULL的定义,看着就觉得不是很痛快。另外,NULL可以由自己定义,这意味着NULL完全有可能被定义成其他东西(少见)。因为NULL并非标准,所以有人可能自己定义了Null或null或其他东西(少见),这会带来混乱。

  那么直接用0来表示空指针好了。用0表示写起来简单,而且0就是0,不会有其他定义,只是不那么直观。

  但是用0也好,用NULL也好,都有一个先天劣势,就是在类型匹配时它会被优先当成整数,在一些情况下会带来麻烦。比如:

void fun(int*)
{
    std::cout << "pointer" << std::endl;
}

void fun(int)
{
    std::cout << "int" << std::endl;
}

  上面的fun有两种重载形式,一种是以整数为参数,一种是以整数指针为参数。假设现在,想要传空指针给fun,要怎么写。

  写成fun(0),毫无疑问,这里打印的会是“int”,因为0被当成一个整数。为了让它调用第一个版本的函数,我们需要明确的传递一个指针,写成fun((int*)0),函数调用正确。

  假设还有一个fun(char*)版本的函数,那岂不是要写成fun((char*)0)。吹毛求疵的人可能会觉得这样不好,因为空指针的表示不一致,需要根据不同情况做强制转化。

  这时,NULL又被想起,我们可以这样定义#define NULL ((void*)0),这样NULL就真真切切是个指针了。在C语言里,这是行得通的。可惜这在C++里不行,因为C++中void*并不能隐式转换成int*或其他类型的指针。仍旧需要fun((int*)NULL)和fun((char*)NULL),这样更丑。

  既然强制转换无可避免,相比之下,还是0好一点。

  但实际上前面提到的两种方法不只不恰当,严格来说还不准确。早期C++著作The Annotated C++ Reference Manual(ARM)里指出:“Note that the null pointer need not be represented by the same bit pattern as the integer 0.”也就是说空指针并不一定是0。因此不管是直接写成0,还是用宏来表示都不准确的。只是大多数人(包括我)一直这么用,也一直没出什么问题。

  工作时因为项目早期代码基本都是采用NULL,为了保持编码风格的一致性,我也一直沿用这一写法。

  而平时偶然写代码则更倾向于直接使用0,最直接的原因是每次要使用NULL时都要关注一下它是不是已经不定义了,在没定义的情况下自己还要定义一个,感觉挺麻烦的。

  总的结论是:具体的选择只是看个人喜好。