将std :: feek_ptr与std :: shared_ptr一起阴影

Using std::weak_ptr with std::shared_ptr for shadowing

本文关键字:ptr std 一起 阴影 shared feek      更新时间:2023-10-16

cppreference上std::weak_ptr的文档说

有效返回expired() ? shared_ptr<T>() : shared_ptr<T>(*this),原子执行。

我的判断和其他答案已经确认以下内容不容易参加比赛

int main() {
    auto s_ptr = std::make_shared<T>(...);
    auto w_ptr = std::weak_ptr<T>{s_ptr};
    auto one = std::thread{[&]() {
        auto ptr = w_ptr.lock();
        if (ptr) { ... }
    }};
    s_ptr = std::make_shared<T>(...);
    one.join();
}

但是,这可以可靠地用于在程序中遮蔽计算吗?通过阴影,我的意思是这样的东西

auto s_ptr = std::make_shared<T>(...);
auto w_ptr = std::weak_ptr<T>{s_ptr};
// thread one
while (...) {
    auto ptr = w_ptr.lock();
    cout << "Value contained is " << *ptr << endl;
}
// thread two
while (...) {
     // do the heavy computation on the side
     auto new_value = fetch_new_value();
     // then "atomically" swap
     s_ptr = std::make_shared<T>(std::move(new_value));
}

这里令人困惑的部分是.lock()返回的内容。它可以返回nullptr吗?所有文档都表明该操作将被原子执行。不说这种相互排斥的含义。shared_ptr::operator=中的指针是null的状态吗?weak_ptr可以访问此状态吗?CPReference上shared_ptr::operator=的文档似乎并未提及这一点。

一旦您的共享指针获得新值,您的弱指针将开始返回 nullptr,原因是,一旦您的共享指针开始指向另一个对象,原始对象就会立即被销毁。

但是,由于交接是原子的,因此不会交换指针的行为。

(尽管w_ptr.lock()返回的nullptr值共享的指针不确定,并且可能会崩溃该程序)。

)。

每当您的共享指针重置新值时,您都需要获得一个新的弱指针。但是,当您lock()时,共享指针是否仍指向该新价值,您的弱指针是任何人的猜测。

与控制集团(参考计数)有关的任何事物都是原子。因此,获得新的弱指针是安全的,但不能保证指向任何东西(如果其他线程可以访问您的共享指针)。

此代码可以执行UB:

auto s_ptr = std::make_shared<T>(...);
auto w_ptr = std::weak_ptr<T>{s_ptr};
// thread one
while (...) { // A
  auto ptr = w_ptr.lock(); // B
  cout << "Value contained is " << *ptr << endl; // C
}
// thread two
while (...) {
  // do the heavy computation on the side
  auto new_value = fetch_new_value();
  // then "atomically" swap
  s_ptr = std::make_shared<T>(std::move(new_value)); // X
}

如果线程两个执行// X在线程执行// B之前,weak_ptr不再是指任何数据。

.lock()然后返回一个" null" shared_ptr,您可以在// C上取消。

如果您对ptr的使用避免了无效,则不会显而易见。