智能指针

为什么会出现智能指针:

智能指针是用来智能的管理指针指向的动态资源的释放。由于C++中没有内存的自动回收机制,因此,每次new出来的空间都需要delete,但是有些情况下,总是无法及时的delete,或者由于异常导致程序提早退出,造成内存泄露,因此为了解决内存泄露的问题,产生了智能指针。智能指针是将对内存的管理交付给对象,因此当对象析构时就能够清理资源,有效的避免内存泄露问题。


智能指针的种类:auto_ptr, unique_ptr, shared_ptr, shared_ptr。


auto_ptr:

实际上利用的是管理权限的转移,通过赋值运算符重载或者拷贝构造时,把p1置空,即将p1开辟的空间的管理权限交付给p2后,当我们再去访问旧指针时候,就会出错。因此此设计本身带有缺陷,建议什么情况下都不要使用。


unique_ptr:

为了解决auto_ptr转移管理权带来的弊端,因此使用了unique_ptr,unique_ptr一个对象只能指向一块给定的内存,也就是不支持拷贝和赋值。防止拷贝,可以解决atuo_ptr的问题。
做法:1.把拷贝构造和赋值运算符的操作只声明,不定义。
2.为了防止定义,在将声明私有。


shared_ptr:

核心思想: 引入了计数,使得多个指针可以指向同一块空间,当最后一个指针释放时才真正的释放这块空间。
但是存在弊端:循环引用的问题。
循环引用:
举个例子:
比如一个双向链表,定义了两个块空间,Node1,Node2。两个指针sp1,sp2。 sp1和sp2->prev都指向Node1,所以sp1的引用计数为2,同理,sp1->next 和sp2都指向Node2,所以sp2的引用计数也是2。
当我们想要销毁某一个节点的时候,需要先将引用计数置为1,假如我们delete sp2这块空间,我们就需要将sp2的引用计数置为1,就是说我们需要将sp1->next这个指针销毁掉。把sp2->next销毁,就意味着先把sp1销毁。如果想把sp1销毁,就要把sp1的引用计数置为1,所以,我们就要把sp2->prev销毁,要想把sp2->prev销毁,就代表先要把sp2销毁,这样一来就陷入了无限循环中。

在shared_ptr中,只有当引用计数减减之后等于0,析构时才会释放对象,但是如果析构对象时先析构sp2,但是由于sp2的空间sp1还在使用,所以使用sp2.use_count减减之后为1,不释放。sp1也是同样的道理,由于sp1空间sp2还在使用中,所以sp1.use_count减减之后,也不释放。sp1等着sp2先释放,sp2等着sp1先释放,二者互不相让,引用计数无法达到0,因此无法释放堆上的资源导致最终都没有释放成功,造成内存泄露。

解决循环引用的方法:
使用弱指针-------weak_ptr------,weak_ptr不增加引用计数。weak_ptr不能算是智能指针,因为它没有重载->和*,可以将weak_ptr理解成是一个shared_ptr的辅助工具,weak_ptr是shared_ptr的一个观察者,他只对shared_ptr进行了引用,而没有改变shared_ptr的引用计数,当weak_ptr看到shared_ptr失效后,weak_ptr也会相应失效。


4种智能指针的应用场景:

1.拒绝使用auto_ptr(管理单个堆对象)
2.在确定无需对象共享的情况下,使用unique_ptr,管理单个堆对象
3.在对象被共享的情况下,使用shared_ptr
4.在需要访问shared_ptr对象,又不想改变其引用计数的时候(就是为了防止循环引用),使用weak_ptr;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值