智能指针原理、使用和实现——C++11新特性(三)
weak_ptr不⽀持RAII,也不⽀持访问资源,所以我们看⽂档发现weak_ptr构造时不⽀持绑定到资源,只⽀持绑定shared_ptr,绑定到shared_ptr时,不增加shared_ptr的引⽤计数,那么就可以解决上述的循环引⽤问题。也可以这样想:n1的资源什么时候释放,因为n2还在用呢,需要n2的资源释放掉,那么n2的资源什么时候释放,因为n1还在用呢,需要n1的资源释放掉。智能指针简称
一、智能指针的理解
问题:什么是智能指针?为什么要有智能指针?智能指针解决什么样的问题?
要明白上面这些问题,我们先引入一个程序。
代码语言:javascript
AI代码解释
double div(double x, double y)
{
int* p = new int(120);
if (y == 0)
{
string s = "y can not be zero.";
throw s;
}
delete p;
return x / y;
}
int main()
{
try
{
double x = 2, y = 0;
div(x, y);
}
catch (string s)
{
cout << s << endl;
}
return 0;
}
上面这段程序,如果出现抛异常的话,p的内存是没有办法释放的。
智能指针简称RAll,是一种自动化管理资源的类模板,这里指的资源可以是:动态开辟的内存,文件指针,网络连接,互斥锁等等。RAII在获取资源时把资源委托给⼀个对象,接着控制对资源的访问,利用对象的⽣命周期结束时会自动析构的特性来完成对资源的自动释放,这样保障了资源的正常释放,避免资源泄漏问题。
二、智能指针的类型
智能指针其实就是在原指针的基础上套一个类,如果就这样简单的想会有一个非常致命问题——当一块空间被两个智能指针对象指向时会析构两次,从而引发编译器报错。
库中的智能指针有很多,用法都一样,区别在于处理同一块空间会被释放两次的方法不同。接下来我们就来看这些智能指针是如何处理的。
- auto_ptr:在做拷贝构造和赋值重载时,把原对象的资源管理权直接转移给新的对象,原对象指向空,保证一块资源只被一个智能指针管理,从而达到一块资源只被释放一次的目的。但是这种做法会使原指针悬空,如果被误用会导致访问报错的问题。推荐指数:⭐
- unique_ptr:不允许做拷贝构造和赋值重载操作,从而达到一块资源只被释放一次的目的。如果用不到这两个函数的话可以考虑用这个智能指针。推荐指数:⭐⭐⭐⭐
- shared_ptr:支持多个对象指向同一块资源,它底层用的是引用计数的方法,这是一个很优秀的智能指针,在下文我们会重点来学习该指针的具体原理和实现。推荐指数:⭐⭐⭐⭐⭐
三、智能指针的使用
这里就以shared_ptr为例,其他都是一样的,首先shared_ptr本质就是一个类模板,需要我们传入模板参数,比如我们需要让它管理一个int类型的指针。那么它的类型就是:
shared_ptr<int>
然后只需要我们创建变量和传入手动申请的空间进行构造。如:
shared_ptr<int> p(new int);
四、shared_ptr的原理
1.引用计数
原理:使用一个变量记录有几个对象在管理该资源,从而决定是否释放该资源。例如:当一个对象走到析构函数时也就是该对象生命结束了不再管理这块资源了,所以引用计数减一,此时如果引用计数变成0的话说明该资源没有对象管理了,可以直接释放,如果不是0,说明还有对象在管理,所以不用处理。
2.循环引用问题

例如这样一个环形链表,当n1生命周期结束时发现,还有对象(n2的_next)在指向它,所以没有释放资源,当n2生命周期结束时发现还有对象(n1的_next)指向它,所以也没有释放资源。
也可以这样想:n1的资源什么时候释放,因为n2还在用呢,需要n2的资源释放掉,那么n2的资源什么时候释放,因为n1还在用呢,需要n1的资源释放掉。循环往复始终释放不了,所以导致内存泄漏。
3.weak_ptr处理逻辑
shared_ptr虽然很优秀,但依旧有缺陷——循环引用问题,所以就有了weak_ptr用来辅助shared_ptr来解决这个问题。
weak_ptr不⽀持RAII,也不⽀持访问资源,所以我们看⽂档发现weak_ptr构造时不⽀持绑定到资源,只⽀持绑定shared_ptr,绑定到shared_ptr时,不增加shared_ptr的引⽤计数,那么就可以解决上述的循环引⽤问题。weak_ptr没有重载operator*和operator->等,因为他不参与资源管理,那么如果他绑定的shared_ptr已经释放了资源,那么他去访问资源就是很危险的。weak_ptr⽀持expired检查指向的资源是否过期,use_count也可获取shared_ptr的引⽤计数,weak_ptr想访问资源时,可以调⽤lock返回⼀个管理资源的shared_ptr,如果资源已经被释放,返回的shared_ptr是⼀个空对象,如果资源没有释放,则通过返回的shared_ptr访问资源是安全的。
更多推荐

所有评论(0)