C++智能指针原理

参考文献

1.C++智能指针
2.C++智能指针简单剖析
3.智能指针 auto_ptr 详解
4.C++智能指针详解
5.请你介绍一下C++的智能指针——牛客网


一.什么是智能指针?为什么要有智能指针?

在C++程序里,使用new关键字开辟的内存必须被手动delete掉,不然就会导致内存的泄漏,但是,当程序非常冗长,你能保证自己每一个手动开辟的内存块都释放了吗?在delete之前,倘若程序因为异常跳转后,你还能保证内存被释放吗?为了解决这种因为遗忘或者异常处理而导致内存泄漏的问题,我们就要用智能指针。

智能指针运用了一种叫做RAII的技术,即利用对象生命周期来控制程序资源的技术,这中技术的思想就是在构建对象时获取我们资源的指针,接着控制对资源的访问使之在对象的生命周期内一直保持有效,在对象析构时释放指针对应的内存块。这样,内存块的管理与释放就完全交给了一个对象,这样做的好处有两点:
【1】不需要显示的释放资源
【2】对象所需的资源在其生命周期内始终有效。

在智能指针的发展历程中,C++不断推出了各种各样的智能指针。但在赋值/拷贝过程,但他们都个有缺陷,直到今日,shared_ptr才算一种成熟的智能指针,下面来分别介绍这几种指针。


二.各种智能指针

1.auto_ptr

评价:最早出现的智能指针,但是性能也是最差的。

原理:在拷贝 / 赋值过程中,直接剥夺原对象对内存的控制权,转交给新对象,然后再将原对象指针置为nullptr。这种做法也叫管理权转移。他的缺点不言而喻,当我们再次去访问原对象时,程序就会报错,所以auto_ptr可以说实现的不好,很多企业在其库内也是要求不准使用auto_ptr。

2.unique_ptr

评价:在C++11中推出的智能指针,解决了auto_ptr的部分问题。

原理:直接把拷贝构造/赋值函数弄成delete,即将这两个函数定义成已删除的函数,任何试图调用它的行为将产生编译期错误。是C++11标准的内容。C++的做法是将这两个函数设为私有,且只声明不实现。
这种智能指针比起auto_ptr要好上不少,且实现简单。但是遇到要拷贝构造 / 赋值的情景就会哑火,所以只能算中规中矩。

3.shared_ptr

评价:shared_ptr完善了前两种的不足,既不会直接剥夺原对象对内存的控制权,也允许进行拷贝构造和赋值,这都源自于他引入了一个新的标志——引用计数。

原理:是通过引用计数的方式来实现多个shared_ptr对象之间共享资源。shared_ptr在其内部,给每个资源都维护了着一份计数,用来记录该份资源被几个对象共享。在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减一。如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源;如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对象就成野指针了。

4.weak_ptr

问题:shared_ptr所导致的循环引用的问题:
当前的shared_ptr已经能解决绝大多数的问题了,但还是有一点点的瑕疵。就是在循环引用的时候还会造成内存泄漏。

解决方法:C++库为了解决这个问题,专门定义了一个叫做weak_ptr的东西,专门用于辅助shared_ptr来解决引用计数的问题。那他是怎么解决这么问题的呢?当shared_ptr内部要监视其他的shared_ptr对象时,类型就采用weak_ptr。这种weak_ptr在指向被监视的shared_ptr后,并不会使被监视的引用计数增加,且当被监视的对象析构后就自动失效。
然后它就什么都不管光是个删 , 也就是这里的cur和next在析构的时候 , 不用引用计数减一 , 直接删除结点就好。这样也就间接地解决了循环引用的问题,当然week_ptr指针的功能不是只有这一个。但是现在我们只要知道它可以解决循环引用就好。


补充:智能指针是线程安全的吗?

【1】对于unique_ptr,由于只是在当前代码块范围内有效。所以不涉及线程安全的问题;
【2】对于shared_ptr,多个对象要同时共用一个引用计数变量,所以会存在线程安全的问题,但是标准库实现的时候考虑到了这一点,使用了基于原子操作(CAS)的方式来保证shared_ptr能够高效,原子的操作引用计数。

最后总结一下我们学过的这几种智能指针

【1】不要使用auto_ptr,因为他的缺陷导致我们拷贝构造/赋值的时候有很大的麻烦;
【2】在不需要拷贝构造/赋值的时候,可以使用unique_ptr;
【3】有拷贝构造/赋值的情况,推荐使用shared_ptr;
【4】类内有访问其他shared_ptr对象时,指针类型设为weak_ptr,可以不改变其他shared_ptr对象的引用计数;
【5】代码中尽量不用delete关键字,因为我们的内存的管理与释放全权交给对象处理;

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值