一 weak_ptr
看名字就知道,他是一个弱引用,他的存在是为了辅助shared_ptr的循环引用问题,它不占用引用数。只能通过shared_ptr或者weak_ptr构造赋值。
它没有重载 * 和 -> 运算符,因此不可以直接通过 weak_ptr 访问对象,典型的用法是通过 lock() 成员函数来获得 shared_ptr,进而使用对象。
大家理解时,将weak_ptr看成用来监视shared_ptr(强引用)的生命周期用。是一种对shared_ptr的扩充。
1 weak_ptr初始化赋值
//1 weak_ptr初始化赋值
std::shared_ptr<int> sh = std::make_shared<int>(); // 默认值为0
cout<<sh.use_count()<<endl; // 1
std::weak_ptr<int> w(sh); // 用shared_ptr构造
std::weak_ptr<int> w1(w); // 用weak_ptr构造
cout<<sh.use_count()<<endl; // 1
std::weak_ptr<int> w2=sh; // 用shared_ptr赋值
std::weak_ptr<int> w3=w2; // 用weak_ptr赋值
cout<<sh.use_count()<<endl; // 1
2 lock()函数
lock():检查weak_ptr所指向的对象是否存在,如果存在那么lock将返回一个指向该对象的shared_ptr(指向对象的强引用就会+1),如果指向对象不存在,lock会返回一个空的shared_ptr。通过lock可以将weak_ptr转化成shared_ptr使用。
例子看下面。
3 expired()函数
expired函数:判断weak_ptr的方法expired判断shared_ptr管理的资源是否已经释放。true已释放,0未释放。
4 上面1,2,3大点的案例
注释已经标明清楚。
//4 weak_ptr --小弟
void test16(){
//1 weak_ptr初始化赋值
std::shared_ptr<int> sh = std::make_shared<int>(); // 默认值为0
cout<<sh.use_count()<<endl; // 1
std::weak_ptr<int> w(sh); // 用shared_ptr构造
std::weak_ptr<int> w1(w); // 用weak_ptr构造
cout<<sh.use_count()<<endl; // 1
std::weak_ptr<int> w2=sh; // 用shared_ptr赋值
std::weak_ptr<int> w3=w2; // 用weak_ptr赋值
cout<<sh.use_count()<<endl; // 1
/*
2. lock函数:检查weak_ptr所指向的对象是否存在,
如果存在那么lock将返回一个指向该对象的shared_ptr(指向对象的强引用就会+1),
如果指向对象不存在,lock会返回一个空的shared_ptr.
通过lock可以将weak_ptr转化成shared_ptr使用
*/
std::shared_ptr<int> another = w2.lock();
if (another != nullptr){
*another = 12;
cout<<"sh管理的内存未被释放"<<endl;
}
cout<<sh.use_count()<<endl; // 2
//3 expired函数:判断weak_ptr的方法expired判断shared_ptr管理的资源是否已经释放。true已释放,0未释放
bool isDeleted = w2.expired();
cout<<sh.use_count()<<endl; // 2
cout<<isDeleted<<endl; // 0 因为程序还没结束 sh与another在引用
//测试lock为空时
another.reset();//无参reset置空,该内存引用数减1,本对象another的引用计数为0
sh.reset();
if (w2.lock() == nullptr){
cout<<"sh管理的内存被释放"<<endl;
}
}
结果:
注意,在shared_ptr之前我们已经说过了reset的使用,这里再简单说明一下。
reset():将该引用的引用计数设置为空,不影响该片内存的引用计数,但是该片内存的引用计数会减少1。
5 尺寸问题
weak_ptr与shared_ptr的尺寸一样大,是裸指针的两倍。内部有两个裸指针。
- 1)第一个裸指针指向的是这个智能指针所指向的对象。
- 2)第二个所指针指向一个数据结构(控制块),这个控制块里有:
1、引用计数(强引用计数、弱引用计数)
2、其他数据(弱引用删除器,互斥锁等等)