3

在 shared_ptr 智能指针中,使用了引用计数。然而,引用计数有一个问题,它不能打破引用循环。

我对这个问题有四个问题。

1) 谁能给我一个参考周期发生的片段?

2)如果不能打破引用循环,RCSP如何保证成功的资源管理?有什么办法可以打破第 3 方产品的循环?

3)有没有办法避免参考循环?

4)其他智能指针怎么样?他们如何处理源头管理?例如,share_ptr、scope_ptr?

非常感谢!

4

2 回答 2

11

避免循环的常用方法是在循环的任何一点使用弱引用。shared_ptr有一个伴生类型 ,weak_ptr就是为此目的而设计的。

削弱周期的哪一部分是设计问题。在“父”对象拥有“子”的设计中,从父对象到子对象的引用应该是强的(shared_ptr),而从子对象返回到父对象的引用应该是弱的(weak_ptr)。

于 2010-02-27T00:47:44.950 回答
7

涉及循环的实际用途有很多种图。一个微不足道的片段(尽管在现实生活中不太可能发生)将类似于:

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 结合使用;您可以使用 shared_ptr 而无需使用weak_ptr,但是要在某些时候真正使用weak_ptr,您必须将其转换为shared_ptr。

于 2010-02-27T03:45:47.320 回答