我有一个对象 A
包含共享资源 (shared_ptr) r
, A
是 r
的创建者/所有者在构建时,对象“注册”了它的 r
与另一个对象 B。对象 B 持有对 A
的引用的 r
在std::set
.对象 A 用作 Boost::asio::handler。
我需要注销 r
来自 B
什么时候A
正在被破坏,当A
拥有对 r
的独特访问权, 作为 A
是r
它的创造者负责摧毁它。注意:A作为boost::asio handler时是多次复制构造的.在这里持有 unque acces 意味着没有发生任何 asio 操作(因为如果它们是引用计数将> 2,因为复制了 A
)。
目前,唯一访问权限可由 r.use_count() == 2
测试因为当没有异步操作发生时 A 和 B 都可以访问该对象。但是,我认为这个测试在逻辑上不合理。
我认为我应该将 B 的容器从 std::set<boost::shared_ptr<r> >
更改为至 std:set<boost::weak_ptr<r> >
这样r.unique()
当没有发生异步操作时逻辑上为真。这是对 weak_ptr
的合理使用吗? ?
A
的构造函数和析构函数(in_process_invoker) 以及 register(connect) 和 unregister(disconect) 事件在我的代码中如下所示:
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);
}
}
编辑
我更改了我的设计以使用原始指针,默认构造函数将调用程序标记为主要调用程序并将其拷贝标记为非主要调用程序。当主要对象被销毁时,它会释放内存。
最佳答案
如果您确定当A
执行引用计数测试时,B
持有的引用仍然存在,那么为什么要使用任何一种智能指针B
,为什么不是原始指针?如果您不知道 B
仍会保留引用,那么当前的 == 2
测试不仅不合理,而且是不正确的。
我看到 weak_ptr
相对于原始指针的唯一优势是,如果您将来更改内容,则 A
不会注销 B
,因此引用可能悬空,然后 weak_ptr
变得有用,可以告诉 B
发生了什么。根据 B
使用 r
的方式,这甚至可能是不可能的:如果设计在很大程度上依赖于引用始终有效这一事实,那么半途而废的尝试是没有意义的掩盖它不是的情况。
不过,如果 A
通过 shared_ptr
持有对 r
的引用,您可以在任何地方坚持使用 shared_ptr
到代理对象,而 B
使用 shared_ptr
直接保存对 r
的引用。然后让代理对象负责从 B
注销。这样,要销毁的 A
的最后一个拷贝将销毁代理,代理将注销 B
,然后销毁 r
。无需任何人检查 use_count
。
一个类似的选项是 B
持有一个原始指针,并让 r
在其析构函数中注销自身与 B
的注册。使线程安全可能更难,我不确定。
理想情况下,您会为所有权语义使用“正确的”指针类型。如果 B
共同拥有 r
,那么它应该有一个 shared_ptr
,这样 r
就可以安全地比 长寿>一个
。如果 B
不拥有 r
然后使用 weak_ptr
如果 r
可能没有从 B 中注销
在销毁之前(并确保 B
在 weak_ptr
过期时做正确的事情),或者一个原始指针,如果 B
有其他人的保证以确保指针的有效性。
关于c++ - 复杂设计中的 shared_ptr 和逻辑指针所有权用例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7011877/