所以shared_ptr和weak_ptr是线程安全的,如果你在一个给定的线程中有对象实例,并且它们共享一个指向的对象,则可以在一个线程和另一个线程中与它们交互,并且一切正常。
为了使其正常工作,您必须正确使用它们。
wp.expired()
仅适用于执行诸如“从缓冲区中删除每个已过期的弱引用”之类的操作。它对于您放置的目的没有用处。
每个弱指针一旦过期就会保持过期状态。但是,已经被使用的弱指针在您验证其被使用后可能立即变为过期。
if(!wpPtr.expired()) {
shared_ptr<Foo> spFoo = wpPtr.lock();
spFoo->DoSomething();
}
在<<---这里
,我们对于多线程环境下wpPtr
的状态一无所知。它可能过期,也可能没有过期。另一方面:
if(wpPtr.expired()) {
// <<--- there
}
在 <<--- 这里
,我们确实知道弱指针已经过期。
就像文件IO和其他“事务性”操作一样,检查是否可以执行某些操作的唯一方法是尝试执行它。在确定您应该能够执行操作和实际执行操作之间,状态可能会发生变化并且操作可能会失败。
有时候你可以提前知道你几乎肯定无法执行某个操作,这有时很有用,但直到你尝试后你才能确定是否可以执行。尝试执行可能会失败,在这种情况下,您需要处理错误。
if(auto spFoo = wpPtr.lock()) {
spFoo->DoSomething();
}
这是与弱指针交互的“正确”方式。在同一操作中测试弱指针的有效性并获取共享指针。
在if()
头之外创建一个spFoo
是可以接受的,我更喜欢这种技术,因为spFoo
的作用域仅限于其有效的区域。
另一种首选技术是尽早退出:
auto spFoo = wpPtr.lock();
if(!spFoo) return error("wp empty");
spFoo->DoSomething();
这使得代码流程的“预期”执行成为一条不带缩进、条件或跳转的平坦线路。
if (auto spFoo = wpFoo.lock()) {
因为这样(除了 else 块)如果是 nullptr 则没有人能访问 spFoo。 - Ben