shared_ptr和逻辑指针所有权使用案例在一个复杂的设计 [英] shared_ptr and logical pointer ownership use-case in a complex design

查看:184
本文介绍了shared_ptr和逻辑指针所有权使用案例在一个复杂的设计的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含共享资源(shared_ptr) r 的对象 A r 在创建对象寄存器时, r 的创建者/与另一个对象B.对象B持有 std中对 A 的引用 r :: set 。对象A用作Boost :: asio ::处理程序。

I have an Object A that contains a shared resource (shared_ptr) r, A is the creator/owner of r upon construction the object "registers" its r with another object B. Object B holds a reference to A's r in a std::set. Object A is used as a Boost::asio::handler.

我需要从 r 注销当 A 被销毁时,并且 A 保存唯一访问时,c $ c> B r ,因为 A r 负责销毁它。注意:A是用作 boost :: asio处理程序。在这里保持unque acces意味着没有asio操作正在进行(因为如果它们的引用计数将> 2,因为拷贝由 A )。

I need to unregister r from B when A is being destructed, and when A holds unique access to r, as A is r's creator it is responsible for destroying it. Note: A is copy constructed multiple times when it is used as an boost::asio handler. Holding unque acces here means that no asio operations are taking place (because if they were the reference count would be > 2, as copies were made of A).

此时,可以通过 r.use_count()== 2 验证唯一访问,因为A和B都可以访问对象当没有异步操作发生时。

At the moment unique access is testible by r.use_count() == 2 since A and B both have access to the object when no asynchronous operations are taking place. However, I do not find this test logically sensible.

我想我应该从 std :: set< boost :: shared_ptr< r。 > std:set< boost :: weak_ptr< r> > ,以便在没有发生异步操作时, r.unique()在逻辑上为真。这是一个明智的使用 weak_ptr

I think I should change B's container from std::set<boost::shared_ptr<r> > to std:set<boost::weak_ptr<r> > so that r.unique() is logically true when no asynchronous operations are taking place. Is this a sensible use of a weak_ptr ?

A (in_process_invoker)和register(connect)和unregister(disconect)事件的构造函数和析构函数如下所示:

The constructor and destructor of A (in_process_invoker) and the register(connect) and unregister(disconect) events look as follows in my code:

in_process_invoker(BackEnd & b_in)
  : client_data(new ClientData()),
    b(b_in),               
    notification_object(new notification_object_()) 
{
  b.connect(client_data);  
} 

~in_process_invoker()      
{
  if(client_data.unique()) 
  {
    b.disconect(client_data);       
  }

}

>

EDIT

我改变了我的设计使用原始指针,默认构造函数将调用器标记为主调用器,并将其副本标记为非主调。

I changed my design to use raw pointers, the default constructor marks the invoker as the primary invoker and copies of it as not-primary. When the primary is destroyed it frees up the memory.

推荐答案

如果你确定由<$ c $当 A 执行引用计数的测试时,为什么在 B > B ,为什么不是一个原始指针?如果你不知道 B 仍然保存一个引用,则当前的 == 2 测试不是

If you know for sure that the reference held by B will still be there when A performs the test of reference count, then why use any kind of smart pointer in B, why not a raw pointer? And if you don't know that B will still hold a reference then the current == 2 test isn't just non-sensible, it's incorrect.

我看到的一个 weak_ptr 超过原始指针的唯一优势是,如果你以后改变一些东西,使 A 不会注销 B ,因此引用可能会倾斜, weak_ptr 有助于告诉 B 发生了什么。这可能不可能取决于 B 如何使用 r :如果设计很大程度上依赖于引用是

The only advantage I see of a weak_ptr over a raw pointer is that if you change things in future so that A doesn't unregister with B, hence the reference might dangle, then a weak_ptr becomes useful to tell B what's happened. That might not even be possible depending how B uses r: if the design relies heavily on the fact that the reference is always valid then there's no point half-assing an attempt to cover the case that it isn't.

你可以坚持使用 shared_ptr 无论如何,如果 A 通过 shared_ptr保存对 r 的引用到代理对象,而 B shared_ptr 的引用直接保存到 r 。然后使代理对象负责从 B 注销。这样,要销毁的 A 的最后一个副本将销毁代理,并且代理将取消注册 B ,然后销毁 r 。不需要任何人检查 use_count

You could stick with shared_ptr everywhere, though, if A holds the reference to r via a shared_ptr to a proxy object, while B holds the reference with a shared_ptr directly to r. Then make it the responsibility of the proxy object to unregister from B. That way, the last copy of A to be destroyed will destroy the proxy, and the proxy will unregister with B and then destroy r. No need for anyone to check use_count.

类似的选项是 code>保存原始指针,并在其析构函数中使用 r 取消注册自身 B

A similar option is for B to hold a raw pointer, and have r unregister itself with B in its destructor. It might be harder to make that thread-safe, I'm not sure.

理想情况下,你应该使用right指针类型作为所有权语义。如果 B 共同拥有 r ,那么它应该有一个 shared_ptr ,使 r 可以安全地超过 A 。如果 B 没有 r ,则使用 weak_ptr 如果在销毁之前 r 可能没有从 B 注销,并确保 B weak_ptr 已过期时执行正确的操作),或者如果 B 保证其他人确保指针的有效性。

Ideally you'd use the "right" pointer type for the ownership semantics. If B co-owns r, then it should have a shared_ptr, so that r can safely outlive A. If B doesn't own r then use a weak_ptr if r might not be unregistered from B prior to destruction (and make sure B does the right thing when the weak_ptr has expired), or a raw pointer if B has a guarantee from someone else to ensure the validity of the pointer.

这篇关于shared_ptr和逻辑指针所有权使用案例在一个复杂的设计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆