• c++11 enable_shared_from_this


    本质的原因:raw data和引用计数的管理块,可能是分开的

    使用场景: 需要在对象中得到shared ptr, 

    错误的代码:直接构造新的shared_ptr<A>对象,两个shared_ptr objects 是独立的,pointer to the same raw mem. 两个独立的managed objects. 因此会导致undefined behaviour, delete raw data twice, 通常会导致crash.

    class A {
    public:
        std::shared_ptr<A> getShared() {
            return std::shared_ptr<A>(this);
        }
    };
    int main() {
        std::shared_ptr<A> pa = std::make_shared<A>();
        std::shared_ptr<A> pbad = pa->getShared();
        return 0;
    }

    具体场景: 为什么一定要在类的成员函数里面得到this的shared_ptr呢?直接去裸指针this为什么不行?在异步IO的编程中,callback函数通常在另外的线程中调用,跟主线程是分离开的,这是就涉及到一个对象生存期lifetime的概念,

    //blocking GetRawData is trivial since it is done in child thread 
    std::future<RedisRuslt> RedisConnector::AsyncSetDagToRedis(const SBOString&key, PDAG dag, CDBMEnv* env)
    {
    	assert(dag != nullptr);
    	//start one thread to do the heavy setDagToRedis op
    	PDAG tmpDag;
    	dag->Duplicate(&tmpDag, dbmKeepData);
    	std::shared_ptr<DAG> smartDag(tmpDag);
    	return std::async(std::bind(&RedisConnector::AsyncSetSmartDagToRedis, shared_from_this(),key, smartDag, env));}
    }  

    分析:如果redisconnector对象在async函数调用之前就析构了,那么另外线程中调用bind函数时候,this指针就会失效。因此用shared_from_this(),*this对象生存期得到延长.

     boost库的example,是shared_from_this()典型的场景 https://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/tutorial/tutdaytime3/src.html  

    实现原理:利用weak ptr作为桥梁,在需要shared_ptr时,通过weak_ptr构造出临时的shared_ptr对象

    那么weak_ptr何时初始化呢?为什么时候指向shared_ptr呢,显然需要被shared_ptr管理的类对象需要基础一个enable_shared_from_this<T>的基类,基类中有weak_ptr这个class member,初始化的时机,应该在shared_ptr<A>(new A())的时候.

    由此引申出引用的错误案例:

    class D:public boost::enable_shared_from_this<D>
    {
    public:
        D()
        {
            boost::shared_ptr<D> p=shared_from_this();
        }
        void func()
        {
            boost::shared_ptr<D> p=shared_from_this();
        }
        
    };
    int main(){
       D num;
       num.func();
    }

    从上面可以得到,enable_shared_from_this 的成员 weakthis 不是在 enable_shared_from_this 的构造函数中初始化的,而是通过 _internal_accept_owner 来赋初值的。而这个函数是 shared_ptr 在初始化的时候调用的。得出结论:不要在构造函数中使用 shared_from_this.

    如果有多重继承的情况,而且不同的父类都继承了 boost::enable_shared_from_this,则会出现比较怪异的情况,多重继承在 C++ 中原本就是不推荐的,所以应该在应用中尽量避免这种情况。

    源码:

    template<class Y>
    explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
    {
        boost::detail::sp_enable_shared_from_this( this, p, p );
    }
    
    template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe )
    {
        if( pe != 0 )
        {
          //调用 enable_shared_from_this对象的函数  
          pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
        }
    }
    
    
    namespace boost
    {
    
    template<class T> class enable_shared_from_this
    {
    protected:
    
        enable_shared_from_this()
        {
        }
    
        enable_shared_from_this(enable_shared_from_this const &)
        {
        }
    
        enable_shared_from_this & operator=(enable_shared_from_this const &)
        {
            return *this;
        }
    
        ~enable_shared_from_this()
        {
        }
    
    public:
    
        shared_ptr<T> shared_from_this()
        {
            shared_ptr<T> p( weak_this_ );
            BOOST_ASSERT( p.get() == this );
            return p;
        }
    
        shared_ptr<T const> shared_from_this() const
        {
            shared_ptr<T const> p( weak_this_ );
            BOOST_ASSERT( p.get() == this );
            return p;
        }
    
    public: // actually private, but avoids compiler template friendship issues
    
        // Note: invoked automatically by shared_ptr; do not call
        template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const
        {
            if( weak_this_.expired() )
            {
               //shared_ptr通过拷贝构造一个临时的shared_ptr,然后赋值给weak_ptr 
               weak_this_ = shared_ptr<T>( *ppx, py );
            }
        }
    
    private:
    
        mutable weak_ptr<T> weak_this_;
    };
    
    } // namespace boost
    
    #endif  // #ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
    

    A common implementation for enable_shared_from_this is to hold a weak reference (such as std::weak_ptr) to this. The constructors of std::shared_ptr detect the presence of an enable_shared_from_this base and assign the newly created 

     参考链接:

    https://www.cnblogs.com/codingmengmeng/p/9123874.html

    https://github.com/prehistoric-penguin/blog-post/blob/master/2015-05-22-implementation-enable_shared_from_this.md

    http://www.gaccob.com/publish/2013-08-11-boost-smart-ptr.html

    https://blog.csdn.net/ithiker/article/details/51532484

    https://www.cnblogs.com/lzjsky/archive/2011/05/05/2037363.html

  • 相关阅读:
    The Quad
    将OrCAD Capture CIS的设计文件(.dsn)导入到PADS Logic VX.2.3
    OrCAD Capture CIS 16.6 将版本16.6的设计文件另存为版本16.2的设计文件
    Eclipse IDE 添加jar包到Java工程中
    PADS Logic VX.2.3 修改软件界面语言
    切换Allegro PCB Editor
    Allegro PCB Design GXL (legacy) 将brd文件另存为低版本文件
    Allegro PCB Design GXL (legacy) 设置自动保存brd文件
    Could not create an acl object: Role '16'
    windows 下apache开启FastCGI
  • 原文地址:https://www.cnblogs.com/kkshaq/p/10430364.html
Copyright © 2020-2023  润新知