C++ 复杂设计中的共享ptr和逻辑指针所有权用例
我有一个对象C++ 复杂设计中的共享ptr和逻辑指针所有权用例,c++,network-programming,boost-asio,shared-ptr,asynchronous,C++,Network Programming,Boost Asio,Shared Ptr,Asynchronous,我有一个对象A,它包含一个共享资源(shared_ptr)r,A是r的创建者/所有者,在构建时,对象将其r注册到另一个对象B中。对象B在std::set中持有对A的r的引用。对象A用作Boost::asio::处理程序 当A被销毁,并且A拥有r的唯一访问权限时,我需要从B注销r,因为A是r的创建者,它负责销毁它。注意:副本用作副本时会多次构造。在此处保持unque acces意味着没有发生asio操作(因为如果是,则引用计数将大于2,因为副本是由A制作的) 此时可通过r测试唯一访问。使用_cou
A
,它包含一个共享资源(shared_ptr)r
,A
是r
的创建者/所有者,在构建时,对象将其r
注册到另一个对象B中。对象B在std::set
中持有对A
的r
的引用。对象A用作Boost::asio::处理程序
当A
被销毁,并且A
拥有r
的唯一访问权限时,我需要从B
注销r
,因为A
是r
的创建者,它负责销毁它。注意:副本用作副本时会多次构造。在此处保持unque acces意味着没有发生asio操作(因为如果是,则引用计数将大于2,因为副本是由A
制作的)
此时可通过r测试唯一访问。使用_count()==2
,因为A和B都可以在没有异步操作发生时访问对象。然而,我认为这种测试在逻辑上并不合理
我想我应该将B的容器从std::set
更改为std:set
,这样当没有异步操作发生时,r.unique()
在逻辑上是正确的。这是否合理地使用了弱\u ptr
A
(进程内调用程序)的构造函数和析构函数以及注册(连接)和注销(断开)事件在我的代码中如下所示:
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);
}
}
编辑
我将设计更改为使用原始指针,默认构造函数将调用程序标记为主调用程序,并将其副本标记为非主调用程序。当主程序被销毁时,它会释放内存。如果您确信
B
持有的引用在A
执行引用计数测试时仍然存在,那么为什么在B
中使用任何类型的智能指针,为什么不使用原始指针?如果您不知道B
仍将保留一个引用,那么当前的==2
测试不仅是不合理的,而且是不正确的
我所看到的弱ptr
相对于原始指针的唯一优势是,如果您在将来更改内容,使a
不会与B
注销,因此引用可能会悬空,那么弱ptr
将有助于告诉B
发生了什么。这甚至可能不可能,这取决于B
如何使用r
:如果设计在很大程度上依赖于引用始终有效这一事实,那么就没有必要半途而废地试图掩盖它不有效的情况
但是,如果A
通过shared\u ptr
将r
的引用保存到代理对象,而B
将shared\u ptr
的引用直接保存到r
,则您可以在任何地方都坚持使用shared\u ptr
。然后让代理对象负责从B
注销。这样,要销毁的A
的最后一个副本将销毁代理,代理将使用B
注销,然后销毁r
。无需任何人检查使用\u count
类似的选项是B
保存原始指针,并让r
在其析构函数中使用B
注销自身。我不确定,要保证线程安全可能会更难
理想情况下,您应该使用“right”指针类型作为所有权语义。如果
B
共同拥有r
,那么它应该拥有一个共享的\u ptr
,这样r
可以安全地比a
长寿。如果B
不拥有r
,则在销毁之前,如果r
可能未从B
注销,则使用weak\u ptr
(并确保B
在weak\u ptr
过期时做了正确的事情),如果B
有其他人的保证来确保指针的有效性,则使用原始指针。混合使用智能指针和原始指针是不安全的。这个
使用智能指针的全部目的是找到一种方法
管理对象解除分配和原始
指针破坏了这一点,因为没有办法
了解非空原始指针是否有效
在我看来,你使用弱指针的解决方案是合理的
---它清楚地区分了拥有和非拥有
参考资料。我广泛使用了
这种方法,其中某个对象A归某个对象所有
另一个物体B,通过一个长寿命的
共享指针,并且同一对象也是
从任意数量的其他对象C-Z引用
通过弱点。请参阅我对一个相关问题的回答:您应该将其作为一个答案,这两个注释都是可行的答案:好的,我不确定我的注释对您的设置有多适用,但我将尝试在回答中涵盖所有选项……”“混合使用智能指针和原始指针是不安全的。”使用指针、使用
删除、使用算术是不安全的(溢出有UB),一般来说,用C++编程是不安全的。java在其他方面不安全(特别是数据竞争会给人带来意外的结果,甚至Sun在java中也有数据竞争的bug)。