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<class T>  
    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<class C, class T>  
    inline operator T C::*() const    
    { return 0; }             
private:                  
    void operator&() const;  
};  
  
const null_ptr nullptr = {}

5.std::nullptr_t

 

定义于头文件 <cstddef>

  

typedef decltype(nullptr) nullptr_t;

 (C++11 起)
   

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

示例

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

#include <cstddef>
#include <iostream>
 
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

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值