shared_ptr和逻辑指针所有权使用案例在一个复杂的设计 [英] shared_ptr and logical pointer ownership use-case in a complex design
问题描述
我有一个包含共享资源(shared_ptr) r
,的对象
A
r
在创建对象寄存器时,是
r
的创建者/与另一个对象B.对象B持有 std中对
。对象A用作Boost :: asio ::处理程序。 A
的引用 r
:: set
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屋!