• 欢迎浏览“String me = Creater\忠实的资深Linux玩家;”,请文明浏览,理性发言,有侵犯你的权益请邮件我(creater@vip.qq.com).
  • 把任何的失败都当作一次尝试,不要自卑;把所有的成功都想成是一种幸运,不要自傲。
  •    5年前 (2014-04-17)  boost 评论关闭  40 
    文章评分 0 次,平均分 0.0

    首先来看shared_ptr.h

    inline void _sp_set_shared_from_this( ... )
    {
    }
    template<typename T> inline void _sp_set_shared_from_this(shared_ptr<T>* sp, enable_shared_from_this<T>* p)
    {
            if (p)
            {
                    p->_internal_accept_owner( *sp );
            }
    }

    这里对_sp_set_shared_from_this函数进行了重载,目的就是区分shared_ptr<>管理的对象是否继承自enable_shared_from_this.

    class classA
    {
    
    };
    
    class classB : enable_shared_from_this&lt;classB&gt;
    {
    
    };

    当定义为shared_ptr<classA> 时则调用的是第一个函数,当定义为shared_ptr<classB>时则调用第二个函数。

    那么什么时候调用_sp_set_shared_from_this呢?第二个函数的作用是什么呢?

    1.先来看什么时候调用

    shared_ptr(T * p = NULL)
            {
                    m_ptr = p;
                    m_count = new sp_counted_base(1,1);
                    _sp_set_shared_from_this(this, m_ptr);
            }
    
            shared_ptr(const weak_ptr&lt;T&gt;&amp; right)
            {
                    m_ptr = right.get();
                    m_count = right._get_sp();
                    addref();
                    _sp_set_shared_from_this(this, m_ptr);
            }
    
            shared_ptr(const this_type&amp; o)
            {
                    m_ptr = o.m_ptr;
                    m_count = o.m_count;
                    addref();
                    _sp_set_shared_from_this(this, m_ptr);
            }

    不只是上边的构造函数,赋值与复制操作符都会调用。具体的调用_sp_set_shared_from_this哪个重载版本函数,就是依靠m_ptr来推断。

    2._sp_set_shared_from_this函数有什么用呢?

    由前面的说明,已经知道能够调用_sp_set_shared_from_this实际有操作的类都是从enable_shared_from_this继承而来,在其内部实际上委托给了enable_shared_from_this基类

    p-&gt;_internal_accept_owner( *sp );

    这个函数的作用,实际上就是初始化了weak_ptr智能指针,先列出enable_shared_from_this这个类

    template&lt;typename T&gt;
    class enable_shared_from_this
    {
    public:
            shared_ptr&lt;T&gt; shared_from_this()
            {
                    return shared_ptr&lt;T&gt;( weak_this_ );
            }
    public:
            void _internal_accept_owner(const shared_ptr&lt;T&gt;&amp; p)
            {
                    weak_this_ = p;
            }
    private:
            weak_ptr&lt;T&gt; weak_this_;
    };

    weak_ptr智能指针weak_this_的作用就是对shared_ptr进行观测,来看是怎么观测,由上边的_internal_accept_owner函数可以看出,实际上有如下的构造

            weak_ptr(const shared_ptr&lt;T&gt;&amp; right)
            {
                    m_ptr = right.get();
                    m_count = shared_ptr&lt;T&gt;::_get_counted(right);
                    m_count-&gt;weak.inc();
            }

    这里可以看出weak_ptr智能指针,仅仅增加了观测,而没有对shared_ptr的计数器做任何修改。

    综上,sp_set_shared_from_this函数就是为保存T对象的智能指针shared_ptr<T>增加观测智能指针weak_ptr<T>,并初始化。也说明了weak_ptr是依靠shared_ptr而成立的。

    3.来看为什么上说有的类继承自enable_shared_from_this,为什么要继承自他呢?

    继承自他的原因是想使用enable_shared_from_this的以下成员函数,继承他就可以让this变身为shared_ptr

            shared_ptr&lt;T&gt; shared_from_this()
            {
                    return shared_ptr&lt;T&gt;( weak_this_ );
            }

    来看下面的例子

    class classC {
    public:
        classC(): x_(4) {
            cout &lt;&lt; "classC::classC()" &lt;&lt; endl;
        }
    
        ~classC() {
            cout &lt;&lt; "classC::~classC()" &lt;&lt; endl;
        }
    
        void f() {
            shared_ptr&lt;classC&gt; p(this);
            cout &lt;&lt; p-&gt;x_ &lt;&lt; endl;
        }
    
    private:
        int x_;
    };
    
    int main(int argc, char** argv) {
        shared_ptr&lt;classC&gt; x(new classC);
        x-&gt;f();
        return 0;
    }

    这段代码,将会两次析构 ,结果是灾难性的。甚至有的函数传入thsi指针后会被不小心delete,导致悬垂指针。

    但是,我们将上边的部分代码修改成以下的

        void f() {
            shared_ptr&lt;classC&gt; p = shared_from_this();
            cout &lt;&lt; p-&gt;x_ &lt;&lt; endl;
        }

    这样就正确了,这里演示的比较简单,在boost中,使用function,bind等的时候更容易出错。

    4.weak_ptr如何使用

    weak_ptr 不控制对象的生命期,但是它知道对象是否还活着。如果对象还活着,那么它可以提升 为有效的 shared_ptr;如果对象已经死了,提升会失败,返回一个空的 shared_ptr。此行为是线程安全的 。要想使用waek_ptr观测的智能指针share_ptr,必须使用以下的函数

            shared_ptr&lt;T&gt; lock() const
            {
                    if ( !expired() )
                    {
                            return shared_ptr&lt;T&gt;(*this);
                    }
                    return shared_ptr&lt;T&gt;(NULL);
            }

    对观测的shared_ptr增加一个引用计数,然后返回shared_ptr,这样就不会出现多次释放或者悬垂指针了。

     

    除特别注明外,本站所有文章均为String me = "Creater\忠实的资深Linux玩家";原创,转载请注明出处来自http://unix8.net/home.php/3307.html

    关于
    切换注册

    登录

    忘记密码 ?

    切换登录

    注册

    扫一扫二维码分享