3

来自 boost::shared_ptr 的 boost 文档:

因为实现使用引用计数,shared_ptr 实例的循环不会被回收。例如,如果 main() 持有一个 shared_ptr 给 A,它直接或间接持有一个 shared_ptr 回 A,A 的使用计数将为 2。原始 shared_ptr 的破坏将使 A 悬空,使用计数为 1。使用 weak_ptr 来“打破循环。”

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

4

4 回答 4

4

智能指针是如何工作的?他们记住count指向对象的智能指针,并count在新的共享指针控制对象时增加它,并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,并且共享指针不会删除该对象,因此存在内存和资源泄漏。

请参阅 in boost 的文档weak_ptr以了解如何将它们与shared_ptr.

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

于 2013-04-24T06:45:10.407 回答
1

想象一个宝藏。
你的朋友拿了一个箱子,往里面放了一些金子。他还制作了一张地图。
这是一张神奇的地图,有一个条款:如果你烧掉最新的地图,宝藏和黄金都没有了。
你的朋友把地图放在金子正上方的箱子里,为你制作第二张地图,然后用里面的第一张地图关闭箱子。
他给了你第二张地图,然后带着宝藏消失了。
问题是:如果你烧掉你的地图会发生什么?
答案:没什么,宝物还在某处。

为什么?因为最新的地图副本还在宝箱里!

于 2013-04-24T09:24:03.117 回答
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();
}
于 2013-04-24T06:44:11.373 回答
-1

来自Boost 文档

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

你写:

我无法理解这一段

那挺好的; 那是因为你很聪明。这一段毫无意义。如果你认为你明白了,那就意味着你没有。

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

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

当然,独占所有权智能指针也是如此,std::unique_ptr它甚至没有引用计数!

使用weak_ptr 来“打破循环”。

不。避免循环。你不能“打破”一个循环。没有所谓的“打破”循环。

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

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

于 2016-12-27T03:02:18.363 回答