在shared_ptr智能指针中,使用引用计数。但是,引用计数有一个问题,它不能打破引用循环。
我对这个问题有四个问题。
1)有人可以给我一个片段,其中参考周期发生了吗?
2)如果不能打破参考周期,RCSP如何保证成功资源管理?有没有办法打破第三方产品的周期?
3)无论如何都要避免参考周期?
4)其他智能指针怎么样?他们如何处理源管理?例如,share_ptr,scope_ptr?
非常感谢!
答案 0 :(得分:10)
避免循环的常用方法是在循环的任何一个点使用弱引用。 shared_ptr
有一个伴随类型weak_ptr
,专门用于此目的。
减弱周期的哪个部分是设计问题。在“父”对象拥有“子”的设计中,从父级到子级的引用应该是强的(shared_ptr
),并且从子级到父级的引用应该是弱的(weak_ptr
)。 / p>
答案 1 :(得分:6)
涉及周期的实际用途是相当多的图形。一个微不足道的片段(虽然在现实生活中不太可能发生)将类似于:
struct node {
node *next;
};
int create_cycle() {
node *a = new node;
a.next = a;
}
在create_cycle返回之后,我们刚刚分配的节点包含对它自己的引用,但没有其他指向它,所以引用计数器不会收集它,即使它是垃圾。
Chris Jester-Young已经从实用的角度处理了智能指针的循环中断。他没有详细介绍它在内部的工作原理。
weak_ptr是一种双重间接指针。即weak_ptr不直接提供对象的访问权限。相反,要访问该对象,您必须将weak_ptr转换为shared_ptr,然后使用它来获取该对象 - 但是,如果仍然至少有一个其他shared_ptr,那么将weak_ptr转换为shared_ptr的尝试将只会成功托管对象(因此对象具有非零引用计数且仍然存在)。
因此,weak_ptr允许您访问对象,只要它存在,但“知道”对象何时不再存在,并且不允许您访问对象曾经存在的(现在已释放的)内存如果对象已被破坏。
避免周期取决于您正在使用的各种事物。如果你经常处理图表(例如),他们通常几乎无法避免,只是因为你建模的东西有很多周期。否则,嗯......这取决于。我猜想有相当数量的开发人员已经完成了整个职业生涯,而无需创建包含循环的链接结构。其他人平均每周可能会多次这样做。
就其他智能指针而言,如上所述,weak_ptr类型与shared_ptr一起使用;你可以在不使用weak_ptr的情况下使用shared_ptr,但是为了在某些时候真正使用weak_ptr,你必须将它转换为shared_ptr。