【发布时间】:2018-05-23 18:54:33
【问题描述】:
std::weak_ptron cppreference 的文档说明了这一点
有效地返回
expired() ? shared_ptr<T>() : shared_ptr<T>(*this),以原子方式执行。
而且我的判断和other SO answers已经确认以下是不容易出现种族的
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= 中是否存在指针为空的状态? weak_ptr 可以访问此状态吗? shared_ptr::operator= on cppreference 的文档似乎没有提到这一点。
【问题讨论】:
-
我不能引用章节,但我相信 shared_ptr 和它的小伙伴weak_ptr 是线程安全的。
auto ptr = w_ptr.lock()确实可以返回nullptr如果所有 shared_ptr 都已被破坏。在我看来,shared_ptr 和 weak_ptr 是 C++11 的两个最佳特性,即使不是在线程场景中也是如此。 -
你可能想使用这个惯用模式:
if (auto ptr = w_ptr.lock()) { cout << "Value contained is " << *ptr << endl; } else { cout << "Value is dead, Jim." << endl; } -
:-) 是的,如果 share_ptr 没有被破坏是可靠的,weak_ptr 将不会返回 nullptr。 (但如果有人重构代码,这可能会成为“未来的错误”。)
-
嗯,这里有一个更详细的答案。 • stackoverflow.com/questions/14482830/… • 关键是只有控制块本身是线程安全的。
-
据我所知,一旦您的共享指针获得新值,您的弱指针将开始返回
nullptr(因为原始对象已被破坏)。但是不会有未定义的行为(因为切换是原子的)
标签: c++ c++11 thread-safety shared-ptr weak-ptr