【Cpp】NULL与nullptr(C++11起)

一、先来谈谈NULL

NULL是一个宏,其定义如下

#ifndef __cplusplus
#define NULL (void *)0
#else
#define NULL 0
#endif

在C语言中,NULL就是(void *)0,通常用于指示指针没有有效操作对象,以避免野指针的出现

int *p = NULL;
/*业务代码*/
if(NULL != p)
{
    /*解引用p*/
}

由于在C++中,不支持从void *类型到int *类型的隐式类型转化,但是支持int到指针类型的隐式类型转化,所以NULL被宏定义为0之后,指针仍可沿用C中int *p1 = NULL;的习惯

#include 
int main(void)
{
    int *p1 = NULL;//编译器支持
    int *p2 = (void *)0;//报错
    return 0;
}

clipboard_20200218084653.png

从上述情况看来,在C/C++中均支持NULL的类型向指针类型隐式装换,C++也可以完全继续使用NULL,但是,看如下代码:

#include 
void func(int a){}
void func(char *a){}
int main(void)
{
    func(NULL);
    return 0;
}

由于C++中有函数重载机制,而NULL的类型又支持向其它类型的隐式转化,这就势必会导致func(NULL);引起歧义,还好,这样的话编译器会报error,不会引发太大的错误:
【Cpp】NULL与nullptr(C++11起)_第1张图片

二、nullptr的出现

为了解决上述问题,C++11中引入了一个新的关键字nullptr,这个关键字的本质为:

const class nullptr_t{
public:
    template<class T> inline operator T*()const {return 0;}
    template<class C, class T> inline operator T C::*() const {return 0;}
private:
    void operator&() const;
} nullptr={};

其类型为nullptr_t,不属于任何一种对象指针,但是却可以隐式得转换为任何指针类型

#include 
void func(int a){}
void func(char *a){}
int main(void)
{
    func(0);
    func(nullptr);
    return 0;
}

使用0nullptr后,上述代码就可以消除歧义。但是,nullptr还是有其不足之处,如下代码:

#include 
void func(int *a){}
void func(char *a){}
int main(void)
{
    func(nullptr);
    return 0;
}

如果两个同名函数传参个数一致且都是指针类型,如果传入nullptr依旧会引起歧义,编译器也是会报error的:
【Cpp】NULL与nullptr(C++11起)_第2张图片

三、C++中NULL与nullptr的选择与比较

  1. NULL是宏定义,nullptr是关键字
  2. 理论上指针可以完全沿用NULL,编译器也是完全支持的
  3. 如果是一个全新的项目,使用nullptr来标示指针
  4. 如果C++项目中大量使用了NULL,为保持统一,用NULL
  5. C/C++混合开发,用NULL

你可能感兴趣的:(C++,C语言)