繁体   English   中英

为什么 lock() function 必须与 std::weak_ptr 一起使用才能安全地提取 std::shared_ptr?

[英]Why must the lock() function be used with a std::weak_ptr to safely extract the std::shared_ptr?

这是一个示例,它显示了从 weak_ptr 获取 shared_ptr 的两种不同方法:

#include <memory>
#include <iostream>

void print_shared1(std::weak_ptr <int> wp)
{
    // always gets pointer safely
    std::shared_ptr <int> sp(wp.lock());
    std::cout << "wp = " << (sp ? *sp : 0) << std::endl;
}

void print_shared2(std::weak_ptr <int> wp)
{
    // can crash if pointer has been freed
    std::shared_ptr <int> sp(wp);
    std::cout << "wp = " << (sp ? *sp : 0) << std::endl;
}

int main(int argc, char* argv[]) 
{
    std::shared_ptr <int> s = std::make_shared<int>(1);
    std::weak_ptr <int> w = s;

    print_shared1(w);
    print_shared2(w);

    s.reset();
    
    print_shared1(w);
    print_shared2(w);
}

运行时,这是 output:

wp = 1
wp = 1
wp = 0
terminate called after throwing an instance of 'std::bad_weak_ptr'
  what():  bad_weak_ptr
Aborted (core dumped)

显然,仅通过从弱指针构造共享指针来访问弱指针并不总是安全的。

我的问题是:

  1. 在function print_shared2中,为什么在sp的构建过程中没有用到wp.lock()的语义?
  2. std::bad_weak_ptr 到底有什么用?

std::bad_weak_ptr 到底有什么用?

你刚刚看到了它的用途。 lock返回一个空的shared_ptr 构造函数抛出异常。

使用shared_ptr构造函数意味着“我确定这个weak_ptr是有效的,如果不是,那是一个必须立即处理的异常错误情况。” 如果您不确定weak_ptr的状态并想检查它,请使用lock

  1. 有构造函数std::shared_ptr<Y>::shared_ptr(const std::weak_ptr<Y>& r) (11)允许这样做。
  2. 在构造共享指针时,它会检查if (sp)

    请注意, r.lock()可用于相同目的:不同之处在于,如果参数为空,此构造函数将引发异常,而std::weak_ptr<T>::lock()构造一个空的std::shared_ptr在这种情况下。

因为这就是std::shared_ptr构造函数的工作方式。 [util.smartptr.shared.const]

template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
约束Y*T*兼容。
效果:构造一个shared_ptr object 与r共享所有权,并存储存储在r中的指针的副本。 如果抛出异常,则构造函数无效。
置条件: use_count() == r.use_count()
抛出:当bad_weak_ptr r.expired()时出现 bad_weak_ptr。


为什么? 因为这是标准作者决定赋予它的语义。 如果您尝试直接从std::weak_ptr构造std::shared_ptr ,那么您就是在断言weak_ptr是有效的。 如果您不确定,请使用lock

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM