4

当您希望使用弱指针进行访问时,首先建议您通过锁定获得指向对象的强指针。如果指向的对象早先被删除,锁定可能不会成功。

在我看来,除非你在打破循环以确定什么是弱指针时做错了什么,否则锁定将会成功。所以你锁定只是为了交叉检查你的设计。

这个对吗?

我看过一些关于缓存的评论,但它们似乎是对weak_ptrs的滥用。但当然,一个人的虐待是另一个人的创新。我想听听意见。

4

4 回答 4

3

不要将其视为“锁定”,请记住,您所做的只是获得另一份所有权。弱指针本身不拥有任何东西,所以不能直接使用。

弱指针的典型用途可能在于并发代码。假设您在某处有一组由共享指针拥有的对象。然后,您可以拥有另一个引用这些相同对象的弱指针集合(例如,计时器集合)。第二个线程可能会拾取弱指针,尝试从中创建一个共享指针,并在成功时调用对象上的计时器例程。如果任务当时已经死亡,那么共享指针将为空,第二个线程跳过该任务。

关于它的关键事实std::shared_ptr是它的内部引用计数是原子更新的,因此您可以按照我描述的方式编写代码,并且它将是无竞争的。

Thread 1                          Thread 2
--------                          --------
std::set<std::shared_ptr<Task>>   std::list<std::weak_ptr<Task>> todo;
add
remove                            for (auto wp : todo)
                                      if (auto p = wp.lock())
                                          p->do_work();
于 2012-06-12T11:59:42.160 回答
3

,你不应该。

假设您维护一个观察者列表,在销毁时您需要取消订阅观察者对其正在观察的对象的订阅,但这需要观察者维护其观察到的实体的列表,从而导致一个循环。

为了简化设计,引入一个间接级别更简单。观察者和实体之间的代理将允许观察者被销毁并且实体查询其活跃度。

如何 ?只需分配 astd::shared_ptr<Observer>并让实体仅保留 a std::weak_ptr<Observer>,然后当实体迭代其观察者列表时,它可以剔除对自上次迭代以来死亡的人的引用。

于 2012-06-12T12:11:40.220 回答
2

如果您weak_ptr仅用于打破循环,那么是的,shared_ptr从中获得 a 应该总是成功的。

但这不是唯一的用途。Matthieu M. 给出了一个使用它们的例子。

您提到缓存,对于weak_ptr没有循环的情况,这是一个很好的用例,我根本不认为这是一种滥用。如果您有一个系统的其他部分(另一个线程或缓存)拥有的对象,并且您想要存储对该对象的引用以供以后使用,如果您使用 ashared_ptr来引用该对象,那么您共享所有权并将延长其使用寿命。如果您不确定以后是否需要该对象,因此不想延长其生命周期,您可以使用 aweak_ptr并在需要时检查它是否仍然存在。如果它不存在,您会找到不同的对象或再次创建它(这可能会很慢,例如需要数据库查询,这就是为什么您希望尽可能重用现有对象的原因。)

于 2012-06-12T12:34:44.427 回答
0

您拥有weak_ptr无效的用例似乎是竞争条件/糟糕的设计。

weak_ptr应该用于访问具有严格生命周期的对象,访问对象不拥有所有权

如果你有一个非严格生命周期的对象,你应该使用shared_ptr.

于 2012-06-12T11:58:07.253 回答