智能指针 auto_ptr、unique_ptr,shared_ptr

用户申请堆上的空间,会用一个指针指向将其保存起来,以便于对其进行释放,但往往释放的情况有多种,所以有时会忘记释放,有可能会造成内存泄漏。智能指针的提出是为了解决此类问题,将其被封装在一个类中,在构造的时候创建,在析构的时候释放。因为智能指针都是栈空间上类的对象。所以,当函数(程序)运行结束后,会自动调用其析构函数自动释放。

                                                        

智能指针实现的基本思想,利用一个对象的生命周期来控制一份资源的管理(RAII)+对->和*.的重载实现指针的功能。

 

几种常见的智能指针:

  • auto_ptr

      以下就是auto_ptr的实现方式:采用资源管理权的转移,将一个指针所指向的空间交给另一个指针。

但这就引起了auto_ptr的缺点:

管理权一直在变,且只有一个指针指向,两个指针不能指向同一块资源就有很多问题。因为当调用拷贝构造和赋值运算符重载的时候,直接将原来ptr所管理的资源扔掉了,转而交给新的ptr。但这并不是拷贝构造和赋值运算符重载的本意。如下图,执行就会引起程序崩溃。

 

  • unique_ptr

    因为auto_ptr的缺陷,就有其他的智能指针了,unique_ptr的改进就是将一份空间的资源独占,在C++98和C++11中分别对其的防拷贝给出了两种方法:C++98中将拷贝构造和赋值运算符重载给为了private,并且只声明了未定义;C++11将两个函数 = delete,所以当调用这两种方法时编译器会报错。以上都是直接很暴力的方法让指针不能被拷贝。

  • shared_ptr&weak_ptr

     shared_ptr引入了一个计数的方式,记录下有多少个对象共享一份资源空间。让多个指针可以指向同一块空间,在构造的时候检测若指向的是共同一块空间,引用计数+1,在析构的时候检查计数为1再delete这块空间。如下图:

    但引用计数并不是简单的用一个count去维护,因为这个count是多个智能指针对象所共有的,但若是多线程对其进行++或--的操作,会使count同时改变,这时count的值就会“错误”,与我们所想的不一样,最终有可能导致资源未释放或多次释放导致程序崩溃。所以在对count++或--时要加上互斥锁,才能保证线程安全。

     显然这样的智能指针就很好的解决了之前管理权的问题,但是仍然存在一个问题:循环引用,会导致资源空间不能完全释放掉,在双向链表中就会引起此类问题:构建一个结构体用shared_ptr指向_pre和_next,创建两个节点,并建立关系,这时就可以看到p1和p2的_Uses都变为了2,但实际上p1和p2并没有引用同一份空间,所以当调用析构函数的时候,p1和p2的_Uses都只减为1,没有释放掉申请的资源,会引起资源泄露。

这是因为,所以只有_next析构了p2才会释放,_pre析构p1才会释放。但是只有p1释放后,_next才会析构,而p1由_pre管理,_pre又是p2的成员,同理,_pre想要析构,等p2释放了才可以,p2想要释放又得等_next析构才可以。 所以就构成了循环引用。这就是shared_ptr的缺点。

为了解决shared_ptr出现的问题,将ListNode中的_pre和_next改为weak_ptr,因为weak_ptr是使用一个共享的资源而不需要管理权。并且weak_ptr要与shared_ptr配合才能使用。

如下图:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值