Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 复杂设计中的共享ptr和逻辑指针所有权用例_C++_Network Programming_Boost Asio_Shared Ptr_Asynchronous - Fatal编程技术网

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)。