lock() 和 expired() 有什么区别?弱点 C

新手上路,请多包涵

最近我开始使用 C++11。我研究了 weak_ptr 。有两种获取原始指针的方法。

  1. lock() 功能
   shared_ptr<Foo> spFoo = wpPtr.lock();

   if(spFoo) {
       spFoo->DoSomething();
   }

  1. expired() 功能
   if(!wpPtr.expired())
   {
       shared_ptr<Foo> spFoo = wpPtr.lock();
       spFoo->DoSomething();
   }

哪个是更好的方法?这两种方式有什么不同?

原文由 zeno 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

因此,共享 ptr 和弱 ptr 是线程安全的,因为如果您有一个给定线程本地的对象实例,并且它们共享一个共同的指向对象,您可以在一个线程和另一个线程中与它们交互,并且一切正常。

要使其正常工作,您必须正确使用它们。

wp.expired() 仅对“从缓冲区中删除每个过期的弱 ptr”之类的操作有用。它对您放置它的目的没有用。

每个弱指针一旦过期,仍然过期。但是,在您验证它已启用后,已启用的弱指针可能会立即过期。

 if(!wpPtr.expired())  {
  // <<--- here
  shared_ptr<Foo> spFoo = wpPtr.lock();
  spFoo->DoSomething();
}

<<--- here 我们对 wpPtr 在多线程环境中的状态 _一无所知_。它可能已过期或未过期。另一方面:

 if(wpPtr.expired())  {
  // <<--- there
}

<<--- there 我们 知道弱指针已经过期。

与文件 io 和其他类型的“事务”操作一样,检查您是否可以做某事的唯一方法就是 _尝试去做_。在确定您应该能够做到这一点和做到这一点之间,状态可能会发生变化并且操作可能会失败。

有时你可以确定你几乎肯定 _不能早做_,这有时很有用,但在你尝试之前你不能确定你能做到。尝试可能会失败,此时您将处理错误。

 if(auto spFoo = wpPtr.lock())  {
  spFoo->DoSomething();
}

这是与弱指针交互的“正确”方式。测试弱指针的有效性,在同一个操作中得到共享指针。

if() 标头之外创建一个 spFoo 是可以接受的,我更喜欢这种技术,因为 spFoo 的范围仅限于它有效的区域。

另一种首选技术是提前退出:

 auto spFoo = wpPtr.lock();

if(!spFoo) return error("wp empty");

spFoo->DoSomething();

这使得代码的“预期”执行以一条平坦的线流动,没有缩进、条件或跳转。

原文由 Yakk - Adam Nevraumont 发布,翻译遵循 CC BY-SA 4.0 许可协议

第二种变体有两个问题:

  1. 它做了不必要的检查 wpPtr.expired()
  2. 在取消引用之前缺少必要的检查 if (spFoo) spFoo

第一个变体是事务性的,当您最终需要使用弱指针引用的对象时使用它。

原文由 bobah 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题