弱引用智能指针 std::weak_ptr 可以看做是 shared_ptr 的助手,它不管理 shared_ptr 内部的指针。std::weak_ptr 没有重载操作符 * 和 ->,因为它不共享指针,不能操作资源,所以它的构造不会增加引用计数,析构也不会减少引用计数,它的主要作用就是作为一个旁观者监视 shared_ptr 中管理的资源是否存在。
1.初始化
// 默认构造函数
constexpr weak_ptr() noexcept;
// 拷贝构造
weak_ptr (const weak_ptr& x) noexcept;
template <class U> weak_ptr (const weak_ptr<U>& x) noexcept;
// 通过shared_ptr对象构造
template <class U> weak_ptr (const shared_ptr<U>& x) noexcept;/*作者: 苏丙榅
链接: https://subingwen.cn/cpp/weak_ptr/#1-%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95
来源: 爱编程的大丙*/
在 C++11 中,weak_ptr 的初始化可以通过以上提供的构造函数来完成初始化,具体使用方法如下:
#include <iostream>
#include <memory>
using namespace std;int main()
{shared_ptr<int> sp(new int);weak_ptr<int> wp1;weak_ptr<int> wp2(wp1);weak_ptr<int> wp3(sp);weak_ptr<int> wp4;wp4 = sp;weak_ptr<int> wp5;wp5 = wp3;return 0;
}/*作者: 苏丙榅
链接: https://subingwen.cn/cpp/weak_ptr/#1-1-%E5%88%9D%E5%A7%8B%E5%8C%96
来源: 爱编程的大丙*/
-
weak_ptr wp1; 构造了一个空 weak_ptr 对象
-
weak_ptr wp2(wp1); 通过一个空 weak_ptr 对象构造了另一个空 weak_ptr 对象
-
weak_ptr wp3(sp); 通过一个 shared_ptr 对象构造了一个可用的 weak_ptr 实例对象
-
wp4 = sp; 通过一个 shared_ptr 对象构造了一个可用的 weak_ptr 实例对象(这是一个隐式类型转换)
-
wp5 = wp3; 通过一个 weak_ptr 对象构造了一个可用的 weak_ptr 实例对象
其他常用方法
- use_count()
通过调用 std::weak_ptr 类提供的 use_count() 方法可以获得当前所观测资源的引用计数,函数原型如下:
// 函数返回所监测的资源的引用计数
long int use_count() const noexcept;
修改一下上面的测试程序,添加打印资源引用计数的代码:
#include <iostream>
#include <memory>
using namespace std;int main()
{shared_ptr<int> sp(new int);weak_ptr<int> wp1;weak_ptr<int> wp2(wp1);weak_ptr<int> wp3(sp);weak_ptr<int> wp4;wp4 = sp;weak_ptr<int> wp5;wp5 = wp3;cout << "use_count: " << endl;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;return 0;
}
测试程序输出的结果为:
通过打印的结果可以知道,虽然弱引用智能指针 wp3、wp4、wp5 监测的资源是同一个,但是它的引用计数并没有发生任何的变化,也进一步证明了 weak_ptr只是监测资源,并不管理资源。
- expired()
通过调用 std::weak_ptr 类提供的 expired() 方法来判断观测的资源是否已经被释放,函数原型如下:
// 返回true表示资源已经被释放, 返回false表示资源没有被释放
bool expired() const noexcept;
函数的使用方法如下:
#include <iostream>
#include <memory>
using namespace std;int main()
{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;return 0;
}
测试代码输出的结果:
weak_ptr 监测的就是 shared_ptr 管理的资源,当共享智能指针调用 shared.reset(); 之后管理的资源被释放,因此 weak.expired() 函数的结果返回 true,表示监测的资源已经不存在了。
- lock()
通过调用 std::weak_ptr 类提供的 lock() 方法来获取管理所监测资源的 shared_ptr 对象,函数原型如下:
shared_ptr<element_type> lock() const noexcept;
函数的使用方法如下:
#include <iostream>
#include <memory>
using namespace std;int main()
{shared_ptr<int> sp1, sp2;weak_ptr<int> wp;sp1 = std::make_shared<int>(520);wp = sp1;sp2 = wp.lock();cout << "use_count: " << wp.use_count() << endl;sp1.reset();cout << "use_count: " << wp.use_count() << endl;sp1 = wp.lock();cout << "use_count: " << wp.use_count() << endl;cout << "*sp1: " << *sp1 << endl;cout << "*sp2: " << *sp2 << endl;return 0;
}
测试代码输出的结果为:
-
sp2 = wp.lock(); 通过调用 lock() 方法得到一个用于管理 weak_ptr
对象所监测的资源的共享智能指针对象,使用这个对象初始化 sp2,此时所监测资源的引用计数为 2 -
sp1.reset(); 共享智能指针 sp1 被重置,weak_ptr 对象所监测的资源的引用计数减 1
-
sp1 = wp.lock();sp1 重新被初始化,并且管理的还是 weak_ptr 对象所监测的资源,因此引用计数加 1
-
共享智能指针对象 sp1 和 sp2 管理的是同一块内存,因此最终打印的内存中的结果是相同的,都是 520
- reset()
通过调用 std::weak_ptr 类提供的 reset() 方法来清空对象,使其不监测任何资源,函数原型如下:
void reset() noexcept;函数的使用是非常简单的,示例代码如下:#include <iostream>
#include <memory>
using namespace std;int main()
{shared_ptr<int> sp(new int(10));weak_ptr<int> wp(sp);cout << "1. wp " << (wp.expired() ? "is" : "is not") << " expired" << endl;wp.reset();cout << "2. wp " << (wp.expired() ? "is" : "is not") << " expired" << endl;return 0;
}
测试代码输出的结果为:
weak_ptr 对象 sp 被重置之后 wp.reset(); 变成了空对象,不再监测任何资源,因此 wp.expired() 返回 true
转载链接:
https://subingwen.cn/cpp/weak_ptr/#1-2-4-reset