C/C++:0 NULL nullptr nullptr_t联系与区别

1. 从本质上

 1) 0是int型的字面值常量

 2) NULL 是预处理变量,定义在 cstdlib 中,其值是0

 3) nullptr 是 nullptr_t 类型的字面值。

 

2. cstdlib 中 NULL 的定义

 

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

 

之所以这样定义的原因,是因为在C语言中,允许 void* 类型隐式转换为任意指针类型,而C++中不允许这样的强制类型转换,但是可以为任意类型的指针赋0值,因此,在C++中将NULL 定义为0

 

3. 0 比 NULL 好

在网上的资料中,均是一致认为 0 比 NULL 好,因为很多可能会出错的时候,使用 0 更直观,如:

void test(int i){ cout << "in int" << endl; }  
void test(int * i){ cout << "in int *" << endl; }  
  
int main()  
{  
    test(0); //输出 in int  
    test(NULL); //输出 in int  
} 

此时,两个函数调用均会调用参数为 int 的 test,使用 0 调动的版本看起来更加直观,因为 0 本身是一个 int 类型的字面值常量,而会潜意识的认为 NULL 应该是一个指针类型,不利于查错

 

4. nullptr 比 0 更好

nullptr 是 nullptr_t 类型的常量,而该类型定义了转到任意指针类型的转换操作符,同时不允许该类型的对象转换到非指针类型,在上面的调用例子中,使用 nullptr,将会调用第二个函数,输出 “in int*”,因为 nullptr被转换为了int * ,符合我们通常的理解。对于nullptr_t 的类型可以定义如下: 

 

class nullptr_t  
{  
public:  
    template  
    inline operator T*() const    //定义类型转换操作符,使nullptr_t 可转为任意非类成员指针类型  
    { return 0; }  
  
      
    //重载类型转换操作符,使 nullptr_t 可以转换为类 C 中任意的指针类型(数据成员指针/函数成员指针)      
    //对类中数据成员的指针,T 将被推导为数据成员的类型 eg: int (X::*); 此时 T 为 int,C 为 X  
    //对类中函数成员的指针,T 将被推导为函数成员的类型 eg: int (X::*)(int); 此时T 等效于: typedef int (T)(int)  
    template  
    inline operator T C::*() const    
    { return 0; }             
private:                  
    void operator&() const;  
};  
  
const null_ptr nullptr = {}

5.std::nullptr_t

 

定义于头文件 

   

typedef decltype(nullptr) nullptr_t;

  (C++11 起)
     

std::nullptr_t 是空指针字面量 nullptr 的类型。它是既非指针类型亦非指向成员指针类型的独立类型。

示例

若二个重载接受不同指针类型,则需要 std::nullptr_t 的重载以接受空指针常量。

#include 
#include 
 
void f(int* pi)
{
   std::cout << "Pointer to integer overload\n";
}
 
void f(double* pd)
{
   std::cout << "Pointer to double overload\n";
}
 
void f(std::nullptr_t nullp)
{
   std::cout << "null pointer overload\n";
}
 
int main()
{
    int* pi; double* pd;
 
    f(pi);
    f(pd);
    f(nullptr);  // 无 void f(nullptr_t) 可能有歧义
    // f(0);  // 歧义调用:三个函数全部为候选
    // f(NULL); // 若 NULL 是整数空指针常量则为歧义
                // (如在大部分实现中的情况)
}

输出如下:

Pointer to integer overload
Pointer to double overload
null pointer overload

总结:

nullptr 指定空指针值的指针字面量(C++11)

NULL

实现定义的空指针常量 
(宏常量)

is_null_pointer

(C++14)

检查类型是否为 std::nullptr_t 
(类模板)

 

参考来源:1.https://zh.cppreference.com/w/cpp/types/nullptr_t

      2.https://www.cnblogs.com/lsgxeva/p/7785303.html

你可能感兴趣的:(c++)