std::weak_ptr(r弱共享指针)一般使用std::shared_ptr来创建,且它的尺寸和创建它的std::shared_ptr对象尺寸相同,也和std::shared_ptr对象有着相同的控制块。
但std::weak_ptr的创建并不会增加std::shared_ptr的引用计数,而只会增加其自身的引用计数,这部分内容将会在下节继续介绍:
auto spw = std::make_shared<Widget>();
//spw的引用计数并不会增大
std::weak_ptr wpw(spw);
此时若spw被析构,则wpw将空悬,我们可以使用std::weak_ptr的成员函数expired()进行判断。但expired()是非原子操作,所以在多线程编程中,其结果不一定准确:在expired()函数被调用后,另一个线程立即析构std::shared_ptr对象,所以在expired()条件下的处理都是有风险的。
auto spw = std::make_shared<Widget>();
//spw的引用计数并不会增大
std::weak_ptr wpw(spw);
if (wpw.expired()) {
// ....
}
这里提供两种安全获取std::shared_ptr状态的方法:
auto spw = std::make_shared<Widget>();
//spw的引用计数并不会增大
std::weak_ptr wpw(spw);
// 第一种
// 若wpw失效,则spw1结果为nullptr,不会出现访问空指针的情况
// 若wpw未失效,则该操作将std::shared_ptr引用计数+1,保证访问期间不会析构
std::shared_ptr<Widget>spw1 = wpw.lock();
//第二种
//若wpw失效,将抛出异常,否则将引用计数+1,保证访问期间不会析构
std::shared_ptr<Widget> spw3(wpw);
注意:对于std::shared_ptr的控制块,只有当其std::weak_ptr的引用次数为0时才会被释放。