提升shared_ptr循环参考?

时间:2013-04-24 05:51:23

标签: boost shared-ptr smart-pointers cycle weak-ptr

来自boost :: shared_ptr的增强文档:

  

因为实现使用引用计数,循环   shared_ptr实例将不会被回收。例如,如果main()   将shared_ptr保存到A,直接或间接持有   shared_ptr回到A,A的使用计数将是2.毁灭   原始的shared_ptr将使用一个悬空,使用次数为1   weak_ptr“打破周期。”

我无法理解这一段,您是否能提供这种情况的最低范例并解释其后果。

4 个答案:

答案 0 :(得分:4)

智能指针如何工作?它们记住指向对象的智能指针的count,当新的共享指针控制对象时增加此count,如果共享指针失去对{1}}的控制权,则减少count对象

假设您有一个班级:

class A{
public:
    A(){std::cout << "Object created" << std::endl;}
    ~A(){std::cout << "Object destroyed" << std::endl;}
    void setSibling(boost::shared_ptr<A> &sibling){
        m_sibling = sibling;
    }
private:
    boots::shared_ptr<A> m_sibling;    
};

和foo():

void foo(){
    //count increases from 0 to 1 (ptr take control on instance of A)
    boost::shared_ptr<A> ptr(new A); 

    //count increases from 1 to 2 (m_sibling take control on instanse of A)
    ptr->setSibling(ptr); 

    //count decreases from 2 to 1 
    //(ptr is destroyed and lose control on instance of A)
    return; 
}

当调用~A()时,m_sibling将失去控制,但只有当所有共享指针都将丢失控件时才会调用~A()。 因此,在调用foo之后,您无法访问该A实例。但是计数为1且共享指针不会删除该对象,因此您有内存和资源泄漏。

请参阅boost中weak_ptr的文档,了解如何将其与shared_ptr一起使用。

简而言之:弱指针就像共享指针,但不会增加count。如果你有一个从shared_ptr创建的weak_ptr实例到被销毁的对象,如果你试图访问原始指针,weak_prt实例将抛出异常(不会发生段错误)。 boost文档中有一个示例如何使用weak_prt方法正确使用weak_ptr::lock()

答案 1 :(得分:1)

想象一下宝藏 你的朋友拿了一个胸口并放入一些金币。他还制作了一张地图 这是一个带有一个条款的神奇地图:如果你刻录了地图的最新副本,那么宝藏和黄金就会消失 你的朋友将地图放在金色的胸前,为你制作第二张地图,并用第一张地图封闭胸部 他给你第二份地图副本并随宝藏一起消失 问题是:如果你刻录你的地图会发生什么? 答案:没什么,宝藏还在某处。

为什么呢?因为地图的最新副本还在胸前!

答案 2 :(得分:0)

以下是一个示例(请注意,此处永远不会调用~A):

#include <boost/shared_ptr.hpp>
#include <iostream>

using boost::shared_ptr;
struct A
{
    ~A()
    {
        std::cout << "~A()" << std::endl;
    }
    void set_shared_ptr(const shared_ptr<A> &p)
    {
        p_ = p;
    }
    shared_ptr<A> p_;
};

int main()
{
  shared_ptr<A> q(new A);
  q->set_shared_ptr(q);
  q.reset();
}

答案 3 :(得分:-1)

来自Boost documentation

  

因为实现使用引用计数,循环   不会回收shared_ptr实例。

你写道:

  

我无法理解这一段

那很好;这是因为你很聪明。该段没有任何意义。如果你认为你得到它,那就意味着你没有。

循环无法回收,好吧,因为存在循环依赖性!循环的其余部分在回收之前不能回收循环的任何部分,因此您必须将每个对象都销毁在它的破坏开始之前。如果你有循环依赖,它是你程序破碎设计的一部分。不要试图责备智能指针(或引用计数)。

基本依赖性问题的任何部分都与智能指针的实现细节无关; 它是由拥有智能指针的定义引起的:拥有的对象在(最后)拥有指针的析构函数开始运行之前不会被销毁。

当然,对于std::unique_ptr这样的独家所有权智能指针来说也是如此,它甚至没有参考计数!

  

将weak_ptr用于&#34;中断周期。&#34;

唐&#39;吨。避免循环。你不能打破&#34;打破&#34;一个循环。没有&#34;打破&#34;一个周期。

Boost的文档比这里更糟糕。这很危险。它在这样的级别上混合了不变量和实现,它表明对智能指针的语义的理解非常糟糕。

它讲述了虚假信息和反模式自我复制的能力!