C++11新特性——nullptr与智能指针

本文详细探讨了C++11引入的nullptr关键字,以及它与NULL的区别,特别关注了野指针的概念和避免野指针的方法。同时介绍了智能指针在提升代码安全性和解决二义性问题上的作用。

C++11新特性——nullptr与智能指针

  • 本文默认大家了解指针的概念,也许大家都听过什么gc回收机制,内存泄漏等等名词,这些也是c++面试常问的一些问题,尤其是今天就带大家聊聊C++11新出的智能指针,能够更好地帮助程序员,让程序更加安全。

1 野指针

  • 野指针,又称悬挂指针,指的是没有明确指向的指针(注意是没有明确指向,不是没有指向
  • 野指针通常会指向那些不可用的内存区域,如果操作野指针极有可能发生异常
  • 如果不想产生野指针,最有效的方式就是在定义指针的时候顺手初始化

1.1 初始化野指针为空

int *p=0;
int *p=NULL;

2 NULL与nullptr

  • 结合这个置空操作,我们来聊聊NULL与nullptr的区别
  • 我们知道在C/C++中经常使用NULL来代表空指针,而这样做在C++中可能会产生一些问题,所以在C++11标准中新增了nullptr这个关键字,也用来代表空指针
  • 接下来来详细了解以下原因

2.1 NULL

  • 前面我们说过,初始化指针也可以用0来初始化

  • 其实在本质上,定义为NULL和定义为0是一样的,因为C++中我们有一个事先定义好的宏

  • #define NULL 0
    
  • 但这带来的问题就是,我们没法判断这个指针本质上到底是一个整数0还是一个指针

  • 比如这个经常被用来说明问题的函数重载代码

  • #include <iostream>
    using namespace std;
    void isnull(void *c){
        cout << "void*c" << endl;
    }
    void isnull(int n){
        cout << "int n" << endl;
    }
    int main() {
        isnull(0);
        isnull(NULL);//当我们想把它当成指针时,编译器还是认为它是个整数0
        return 0;
    }
    
  • 注意,这里的宏定义只是在C++中是这么定义的,而在C中并不是这么定义的,而是#define NULL (void *)0

  • 你可能会问了:C++中为什么不也这么这么定义,就不会发生这种二义性的问题?

    • 答:因为如果在C++中这么定义,void*是不能隐式转换成其他类型指针的,所以编译器提供的头文件做了相应类型的处理

    • #ifdef _cplusplus
      
      #define NULL 0 //如果是cpp程序,就这么定义
      
      #else
      
      #define NULL((void*)0)//如果是c代码,就这么定义
      
      #endif
      
    • 否则就会像接下来这段代码一样报错

    • #define NULL (void *)0
      
      int main(){
         
         int *p=NULL;//无法完成这样的转化
         
         return 0;
      }
      

      kehou10.cpp:12:22: error: invalid conversion from ‘void*’ to ‘int*’ [-fpermissive]
      12 | #define NULL (void )0
      | ^
      | |
      | void

      kehou10.cpp:16:11: note: in expansion of macro ‘NULL’
      16 | int *p=NULL;
      | ^~~~

  • 所以此时,C++11的nullptr就应运而生了

2.2 新关键字nullptr

  • 使用C++11新标准时,你可能会发现输入null时代码提示给你一个nullptr,但当时我没有去深究

  • nullptr是C++11新引入的特性,C++98标准NULL的升级版本。虽然nullptr是C++11引入的关键字,但是和98版本不同的是,nullptr存在类型,它的类型是nullptr_t。需要特殊说明的是nullptr_t 是C++11~C++20标准特性,但不是C99 ~C17标准的特性,C语言从C23才开始支持nullptr_t。

  • nullptr的底层实现这里不解释(我自己还没看),总之在C++中尽量使用nullptr来作为空指针,提高代码健壮性,解决了NULL的二义性问题

  • void isnull(void *c){
        cout << "void*c" << endl;
    }
    void isnull(int n){
        cout << "int n" << endl;
    }
    int main() {
        isnull(NULL); 	//作为整数被调用
        isnull(nullptr);	//作为指针被调用
        return 0;
    }
    

Reference

  • https://blog.youkuaiyun.com/liuguang841118/article/details/127044025(C++11:nullptr_t与nullptr的原理)
  • http://c.biancheng.net/view/7887.html
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值