目的
- weak_ptr只负责监测shared_ptr的内存资源,不参与管理,因此不会增加引用计数
- weak_ptr处理shared_ptr中因使用不当造成的内存泄漏问题
a. 同一原始地址不能初始化多个共享智能指针
b. 函数不能返回管理了this的共享智能指针对象
c. 共享智能指针不能嵌套循环引用
表示方式
- 弱指针初始化
shared_ptr<int> sp(new int(22));
weak_ptr<int> wp1;
weak_ptr<int> wp2(wp1);//通过弱指针初始化
weak_ptr<int> wp3(sp);//通过共享指针初始化
weak_ptr<int> wp4;
wp4 = wp3;//通过弱指针赋值
weak_ptr<int> wp5;
wp5 = sp;//通过共享指针赋值
- 弱指针成员函数
//查看监测内存资源的引用计数
wp1.use_count()
//弱智能指针判断资源是否已释放expired(),返回的是bool类型
cout << "weak " << (weak.expired() ? "is" : "is not") << " expired" << endl;
//获取监测资源的共享智能指针lock()
shared_ptr<int> sp1 = wp.lock();//赋值给sp2
//reset()重置
wp.reset()
细节
- 同一原始地址初始化多个共享智能指针,并不会增加引用计数,而是每个shared_ptr各自独立,因此会出现同一块地址两次析构的情况
- 函数不能返回管理了this的共享智能指针对象:本质也是同一块地址出现两次析构的情况。解决该问题需要先继承enable_shared_from_this模板类,再调用shared_from_this()方法。解决问题的本质是用weak_ptr的lock()方法来初始化新的shared_ptr
- 共享智能指针不能出现嵌套的循环引用:是使用weak_ptr解开共享智能指针中的嵌套循环
举例
weak_ptr初始化和使用 + shared_ptr存在的问题
//shared_ptr存在的问题
//1.存的是this指针的地址,this指针会被析构两次
//2.循环引用,形成环状结构导致引用计数无法减为0
#include <bits/stdc++.h>
using namespace std;
class Test{
public:
Test(){}
~Test(){
cout << "Test is destroyed..." << endl;
}
//需求,返回共享智能指针对象
shared_ptr<Test> getSharedPtr(){
return shared_ptr<Test>(this);
}
};
//循环引用举例
class TA;
class TB;
class TA{
public:
// shared_ptr<TB> bptr;
weak_ptr<TB> bptr;//通过weak_ptr将闭环打开,修改TA或TB其中一个的就能将闭环打开
~TA(){
cout << "TA is distroyed..." << endl;
}
};
class TB{
public:
// shared_ptr<TA> aptr;
weak_ptr<TA> aptr;
~TB(){
cout << "TB is distroyed..." << endl;
}
};
int main(){
cout << "-----------------弱智能指针的初始化---------------" << endl;
shared_ptr<int> sp(new int(22));
weak_ptr<int> wp1;
weak_ptr<int> wp2(wp1);//通过弱指针初始化
weak_ptr<int> wp3(sp);//通过共享指针初始化
weak_ptr<int> wp4;
wp4 = wp3;//通过弱指针赋值
weak_ptr<int> wp5;
wp5 = sp;//通过共享指针赋值
cout << "----------------弱智能指针查看引用计数use_count:--------------" << endl;
//通过打印的结果可以知道,weak_ptr只是监测资源,并不管理资源
cout << "wp1: " << wp1.use_count() << endl;
cout << "wp2: " << wp2.use_count() << endl;
cout << "wp3: " << wp3.use_count() << endl;
cout << "wp4: " << wp4.use_count() << endl;
cout << "wp5: " << wp5.use_count() << endl;
cout << "----------------弱智能指针判断资源是否已释放expired()和reset():--------------" << endl;
//expired()返回的是bool类型
shared_ptr<int> shared(new int(10));
weak_ptr<int> weak(shared);
cout << "1. weak " << (weak.expired() ? "is" : "is not") << " expired" << endl;
shared.reset();
cout << "2. weak " << (weak.expired() ? "is" : "is not") << " expired" << endl;
cout << "----------------获取监测资源的共享智能指针lock():--------------" << endl;
//wp.lock()获取到的是shared_ptr对象(内存地址+内存地址的值),但此时内存有由多个共享智能指针管理,wp.lock()获取到的内存地址是不变的
shared_ptr<int> sp1, sp2, sp3;
weak_ptr<int> wp;
sp1 = std::make_shared<int>(520);
wp = sp1;
sp2 = wp.lock();//赋值给sp2
cout << "use_count: " << wp.use_count() << endl;
sp1.reset();//释放sp1
cout << "use_count: " << wp.use_count() << endl;
sp1 = wp.lock();//赋值给sp1
cout << "use_count: " << wp.use_count() << endl;
cout << "*sp1: " << *sp1 << endl;
cout << "*sp2: " << *sp2 << endl;
cout << "----------------share存在的问题:原始地址初始化多个共享智能指针--------------" << endl;
Test* t = new Test;
shared_ptr<Test> ptr1(t);
// shared_ptr<Test> ptr2(t);//error:输出了两次析构,原因是由于同一个原始地址初始化了多个共享智能指针,会出现重复析构,因此只能通过ptr1初始化ptr2
shared_ptr<Test> ptr2 = ptr1;
cout << "----------------share存在的问题:函数不能返回管理了this的共享智能指针对象--------------" << endl;
//error:本质还是同一个原始地址初始化了多个共享智能指针
// shared_ptr<Test> thisptr1(new Test);
// cout << "use_count:" << thisptr1.use_count() << endl;
// shared_ptr<Test> thisptr2 = thisptr1->getSharedPtr();
// cout << "use_count:" << thisptr1.use_count() << endl;
cout << "----------------share存在的问题:共享智能指针不能循环引用--------------" << endl;
// shared_ptr<TA> Aptr(new TA);
// shared_ptr<TB> Bptr(new TB);
// cout << "TA对象 use_count:" << Aptr.use_count() << endl;
// cout << "TB对象 use_count:" << Bptr.use_count() << endl;
// Aptr->bptr = Bptr;
// Bptr->aptr = Aptr;
// cout << "TA对象 use_count:" << Aptr.use_count() << endl;
// cout << "TB对象 use_count:" << Bptr.use_count() << endl;
//此时发现,未输出析构语句,说明内存没有释放,出现内存泄漏现象
// system("pause");
return 0;
}
weak_ptr解决share_ptr的问题
//shared_ptr存在的问题
//1.存的是this指针的地址,this指针会被析构两次
//2.循环引用,形成环状结构导致引用计数无法减为0
#include <bits/stdc++.h>
using namespace std;
class Test:public enable_shared_from_this<Test>{//继承enable_shared_from_this模板类,调用里面的shared_from_this()方法
public:
Test(){}
~Test(){
cout << "Test is destroyed..." << endl;
}
//需求,返回共享智能指针对象
shared_ptr<Test> getSharedPtr(){
// return shared_ptr<Test>(this);
return shared_from_this();//解决返回this的共享智能指针,其内部是用weak_ptr.lock()实现
}
};
//循环引用举例
class TA;
class TB;
class TA{
public:
// shared_ptr<TB> bptr;
weak_ptr<TB> bptr;//通过weak_ptr将闭环打开,修改TA或TB其中一个的就能将闭环打开
~TA(){
cout << "TA is distroyed..." << endl;
}
};
class TB{
public:
// shared_ptr<TA> aptr;
weak_ptr<TA> aptr;
~TB(){
cout << "TB is distroyed..." << endl;
}
};
int main(){
cout << "----------------weak解决share:函数不能返回管理了this的共享智能指针对象--------------" << endl;
// error:本质还是同一个原始地址初始化了多个共享智能指针,出现两次析构
//需要继承enable_shared_from_this模板类,调用里面的shared_from_this()方法来解决
#if 0
shared_ptr<Test> thisptr1(new Test);//由于继承,此时会初始化父类中weak_ptr指向此时声明的shared_ptr
cout << "use_count:" << thisptr1.use_count() << endl;
shared_ptr<Test> thisptr2 = thisptr1->getSharedPtr();//返回的是weak_ptr检测的内存对应的shared_ptr
cout << "use_count:" << thisptr1.use_count() << endl;
#endif
cout << "----------------weak解决share:共享智能指针不能出现嵌套的循环引用--------------" << endl;
shared_ptr<TA> Aptr(new TA);
shared_ptr<TB> Bptr(new TB);
cout << "TA对象 use_count:" << Aptr.use_count() << endl;
cout << "TB对象 use_count:" << Bptr.use_count() << endl;
Aptr->bptr = Bptr;
Bptr->aptr = Aptr;
cout << "TA对象 use_count:" << Aptr.use_count() << endl;
cout << "TB对象 use_count:" << Bptr.use_count() << endl;
//此时发现,未输出析构语句,说明内存没有释放,出现内存泄漏现象
//当修改为weak_ptr后,恢复正常,内存正常释放
// system("pause");
return 0;
}
运行结果
参考学习
https://www.bilibili.com/video/BV1bX4y1G7ks