std::weak_ptr
on 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的文档似乎没有提到这一点。
答案 0 :(得分:3)
一旦你的共享指针获得一个新值,你的弱指针就会开始返回nullptr
原因是一旦你的共享指针开始指向另一个对象,原始对象就会被破坏。
但是没有未定义的行为交换指针,因为切换是原子的。
(尽管取消引用nullptr
返回的w_ptr.lock()
值共享指针未定义,可能会导致程序崩溃。
每次使用新值重置共享指针时,都需要获取一个新的弱指针。但是,当你的弱指针lock()
被任何人的猜测时,共享指针是否仍指向该新值。
与控制块(引用计数)相关的任何内容都是原子的。因此,获取一个新的弱指针是线程安全的,但不保证指向任何东西(如果其他线程可以访问您的共享指针)。
答案 1 :(得分:1)
此代码可以执行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()
然后返回&#34; null&#34; shared_ptr
,您可以在// C
处取消引用。
如果你保护ptr
使用它是空的,那么就不会有明显的UB。