溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C++11中std::function的用法

發(fā)布時(shí)間:2021-06-18 13:38:02 來(lái)源:億速云 閱讀:313 作者:chen 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“C++11中std::function的用法”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“C++11中std::function的用法”吧!

目錄
  • 1、源碼準(zhǔn)備

  • 2、std::function簡(jiǎn)介

  • 3、源碼解析

    • 3.1、std::function解析

    • 3.2、std::_Function_handler解析

    • 3.3、_Any_data解析

    • 3.4、std::_Function_base解析

  • 4、總結(jié)

    1、源碼準(zhǔn)備

    本文是基于gcc-4.9.0的源代碼進(jìn)行分析,std::function是C++11才加入標(biāo)準(zhǔn)的,所以低版本的gcc源碼是沒(méi)有std::function的,建議選擇4.9.0或更新的版本去學(xué)習(xí),不同版本的gcc源碼差異應(yīng)該不小,但是原理和設(shè)計(jì)思想的一樣的。
    源碼下載地址:http://ftp.gnu.org/gnu/gcc

    2、std::function簡(jiǎn)介

    類模版std::function是一種通用的多態(tài)函數(shù)包裝器。std::function的實(shí)例可以對(duì)任何可以調(diào)用的目標(biāo)實(shí)體進(jìn)行存儲(chǔ)、復(fù)制、和調(diào)用操作,這些目標(biāo)實(shí)體包括普通函數(shù)指針、類成員函數(shù)指針(第一個(gè)參數(shù)需要傳入對(duì)應(yīng)的this指針)、Lambda表達(dá)式或者某個(gè)類的實(shí)例(前提是這個(gè)類重載了()運(yùn)算符)。std::function對(duì)象是對(duì)C++中現(xiàn)有的可調(diào)用實(shí)體的一種類型安全的包裹(我們知道像函數(shù)指針這類可調(diào)用實(shí)體,是類型不安全的)。

    通常std::function是一個(gè)函數(shù)對(duì)象類,它包裝其它任意的可調(diào)用實(shí)體,被包裝的對(duì)象具有類型為T1,…,TN的N個(gè)參數(shù),并且返回一個(gè)可轉(zhuǎn)換到R類型的值。std::function使用模板轉(zhuǎn)換構(gòu)造函數(shù)接收被包裝的函數(shù)對(duì)象;特別是,閉包類型可以隱式地轉(zhuǎn)換為std::function。最簡(jiǎn)單的理解就是通過(guò)std::function對(duì)C++中各種可調(diào)用實(shí)體的封裝,形成一個(gè)新的可調(diào)用的std::function對(duì)象,讓我們不再糾結(jié)那么多的可調(diào)用實(shí)體之間如何進(jìn)行方便高效的轉(zhuǎn)換。

    3、源碼解析

    3.1、std::function解析

    std::function位于libstdc++-v3\include\std\functional中

    template<typename _Res, typename... _ArgTypes>
    class function<_Res(_ArgTypes...)> : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>, private _Function_base
    {
        typedef _Res _Signature_type(_ArgTypes...);
    
        template<typename _Functor>
        using _Invoke = decltype(__callable_functor(std::declval<_Functor&>())(std::declval<_ArgTypes>()...) );
    
        template<typename _Functor>
        using _Callable = __check_func_return_type<_Invoke<_Functor>, _Res>;
    
        template<typename _Cond, typename _Tp>
        using _Requires = typename enable_if<_Cond::value, _Tp>::type;
    
    public:
        typedef _Res result_type;
    
        function() noexcept
            :_Function_base()
        {
        }
    
        function(nullptr_t) noexcept
            :_Function_base()
        {
        }
    
        template<typename _Res, typename... _ArgTypes>
        function(const function& __x)
            :_Function_base()
        {
            if (static_cast<bool>(__x))
            {
                _M_invoker = __x._M_invoker;
                _M_manager = __x._M_manager;
                __x._M_manager(_M_functor, __x._M_functor, __clone_functor);
            }
        }
    
        function(function&& __x)
            :_Function_base()
        { __x.swap(*this); }
    
        template<typename _Functor, typename = _Requires<_Callable<_Functor>, void>>
        function(_Functor __f)
        {
            typedef _Function_handler<_Signature_type, _Functor> _My_handler;
    
            if (_My_handler::_M_not_empty_function(__f))
            {
                _My_handler::_M_init_functor(_M_functor, std::move(__f));
                _M_invoker = &_My_handler::_M_invoke;
                _M_manager = &_My_handler::_M_manager;
            }
        }
    
        function& operator=(const function& __x)
        {
            function(__x).swap(*this);
            return *this;
        }
    
        function& operator=(function&& __x)
        {
            function(std::move(__x)).swap(*this);
            return *this;
        }
    
        function& operator=(nullptr_t)
        {
            if (_M_manager)
            {
                _M_manager(_M_functor, _M_functor, __destroy_functor);
                _M_manager = 0;
                _M_invoker = 0;
            }
            return *this;
        }
    
        template<typename _Functor>
        _Requires<_Callable<_Functor>, function&> operator=(_Functor&& __f)
        {
            function(std::forward<_Functor>(__f)).swap(*this);
            return *this;
        }
    
        template<typename _Functor>
        function& operator=(reference_wrapper<_Functor> __f) noexcept
        {
            function(__f).swap(*this);
            return *this;
        }
    
        void swap(function& __x)
        {
            std::swap(_M_functor, __x._M_functor);
            std::swap(_M_manager, __x._M_manager);
            std::swap(_M_invoker, __x._M_invoker);
        }
    
         explicit operator bool() const noexcept
         { return !_M_empty(); }
    
        _Res operator()(_ArgTypes... __args) const;
        {
            if (_M_empty())
                __throw_bad_function_call();
            return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
        }
    
    private:
        typedef _Res (*_Invoker_type)(const _Any_data&, _ArgTypes...);
        _Invoker_type _M_invoker;

    從源代碼中可以看出以下幾點(diǎn)信息:

    • 該類是一個(gè)可變參模板類

    • 該類繼承于_Maybe_unary_or_binary_function(不分析)和_Function_base,類成員只有_M_invoker一個(gè),從定義可以看出這是一個(gè)標(biāo)準(zhǔn)的函數(shù)指針

    • 首先分析operator()方法,平時(shí)開發(fā)中std::function使用最多的肯定就是重載的括號(hào)運(yùn)算符了,畢竟最終也是要把它當(dāng)成類似于函數(shù)的形式來(lái)調(diào)用的??梢钥吹給perator()函數(shù)里面調(diào)用了_M_invoker函數(shù),并沒(méi)有什么特殊的處理

    • 既然_M_invoker能被調(diào)用,那就說(shuō)明它肯定被初始化過(guò)了,從調(diào)用時(shí)傳給他的參數(shù)來(lái)看,多了一個(gè)不知道是什么的參數(shù)_M_functor,所以我們可以猜測(cè)_M_invoker并不是直接指向std::function接管的可調(diào)用實(shí)體的,而是一個(gè)類似中間層的東西,在_M_invoker的實(shí)現(xiàn)里面才調(diào)用了我們需要執(zhí)行的那個(gè)真實(shí)的可調(diào)用實(shí)體

    • 只有構(gòu)造函數(shù)function(_Functor __f)對(duì)_M_invoker進(jìn)行了初始化,而使用的就是std::_Function_handler里的方法來(lái)初始化_M_invoker的,std::_Function_handler的實(shí)現(xiàn)在后面會(huì)講到

    • 還是看構(gòu)造函數(shù)function(_Functor __f),因?yàn)閟td::function的目的就是對(duì)我們傳入的可調(diào)用實(shí)體進(jìn)行包裝,這里說(shuō)的可調(diào)用實(shí)體可以是普通函數(shù)指針、類成員函數(shù)指針(第一個(gè)參數(shù)需要傳入對(duì)應(yīng)的this指針)、Lambda表達(dá)式以及某個(gè)類實(shí)例(前提是這個(gè)類重載了()運(yùn)算符),而我們看到在std::function這個(gè)類里面并沒(méi)有直接托管我們傳入的可調(diào)用實(shí)體,而只是調(diào)用了_My_handler::_M_init_functor(_M_functor, std::move(__f)),推測(cè)是由_Function_base來(lái)托管可調(diào)用實(shí)體的

    3.2、std::_Function_handler解析

    std::_Function_handler位于libstdc++-v3\include\std\functional中

    template<typename _Res, typename _Functor, typename... _ArgTypes>
    class _Function_handler<_Res(_ArgTypes...), _Functor> : public _Function_base::_Base_manager<_Functor>
    {
        typedef _Function_base::_Base_manager<_Functor> _Base;
    
    public:
        static _Res _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
        {
            return (*_Base::_M_get_pointer(__functor))(std::forward<_ArgTypes>(__args)...);
        }
    };
    
    template<typename _Functor, typename... _ArgTypes>
    class _Function_handler<void(_ArgTypes...), _Functor> : public _Function_base::_Base_manager<_Functor>
    {
        typedef _Function_base::_Base_manager<_Functor> _Base;
    
    public:
        static void _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
        {
            (*_Base::_M_get_pointer(__functor))(std::forward<_ArgTypes>(__args)...);
        }
    };
    
    template<typename _Res, typename _Functor, typename... _ArgTypes>
    class _Function_handler<_Res(_ArgTypes...), reference_wrapper<_Functor> > : public _Function_base::_Ref_manager<_Functor>
    {
        typedef _Function_base::_Ref_manager<_Functor> _Base;
    
    public:
        static _Res _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
        {
            return __callable_functor(**_Base::_M_get_pointer(__functor))(std::forward<_ArgTypes>(__args)...);
        }
    };
    
    template<typename _Functor, typename... _ArgTypes>
    class _Function_handler<void(_ArgTypes...), reference_wrapper<_Functor> > : public _Function_base::_Ref_manager<_Functor>
    {
        typedef _Function_base::_Ref_manager<_Functor> _Base;
    
    public:
        static void _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
        {
            __callable_functor(**_Base::_M_get_pointer(__functor))(std::forward<_ArgTypes>(__args)...);
        }
    };
    
    template<typename _Class, typename _Member, typename _Res, typename... _ArgTypes>
    class _Function_handler<_Res(_ArgTypes...), _Member _Class::*> : public _Function_handler<void(_ArgTypes...), _Member _Class::*>
    {
        typedef _Function_handler<void(_ArgTypes...), _Member _Class::*> _Base;
    
    public:
        static _Res _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
        {
            return std::mem_fn(_Base::_M_get_pointer(__functor)->__value)(std::forward<_ArgTypes>(__args)...);
        }
    };
    
    template<typename _Class, typename _Member, typename... _ArgTypes>
    class _Function_handler<void(_ArgTypes...), _Member _Class::*> : public _Function_base::_Base_manager<_Simple_type_wrapper< _Member _Class::* > >
    {
        typedef _Member _Class::* _Functor;
        typedef _Simple_type_wrapper<_Functor> _Wrapper;
        typedef _Function_base::_Base_manager<_Wrapper> _Base;
    
    public:
        static bool _M_manager(_Any_data& __dest, const _Any_data& __source, _Manager_operation __op)
        {
            switch (__op)
            {
                #ifdef __GXX_RTTI
                case __get_type_info:
                    __dest._M_access<const type_info*>() = &typeid(_Functor);
                    break;
                #endif
    
                case __get_functor_ptr:
                    __dest._M_access<_Functor*>() = &_Base::_M_get_pointer(__source)->__value;
                    break;
    
                default:
                    _Base::_M_manager(__dest, __source, __op);
            }
            return false;
        }
    
        static void _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
        {
            std::mem_fn(_Base::_M_get_pointer(__functor)->__value)(std::forward<_ArgTypes>(__args)...);
        }
    };

    從源代碼中可以看出_Function_handler有六種重載形式,以下對(duì)其進(jìn)行分類說(shuō)明:

    • 第一個(gè)和第二個(gè)重載形式繼承于std::_Function_base::_Base_manager,當(dāng)std::function接管的可調(diào)用實(shí)體是一個(gè)普通函數(shù)指針、類實(shí)例或者Lambda表達(dá)式時(shí),發(fā)揮作用的就是這兩個(gè)類。里面的內(nèi)容很簡(jiǎn)單,通過(guò)調(diào)用_Function_base::_Base_manager<_Functor>的_M_get_pointer方法從__functor中取出對(duì)應(yīng)的可調(diào)用實(shí)體,然后直接執(zhí)行,我們知道能直接執(zhí)行的可調(diào)用實(shí)體的類型是普通函數(shù)指針、類實(shí)例(必須重載了()運(yùn)算符)或者Lambda表達(dá)式(Lambda其實(shí)本質(zhì)就是一個(gè)匿名的類實(shí)例)。這兩個(gè)重載形式的唯一區(qū)別就是它們一個(gè)處理函數(shù)有返回值的情況,另一個(gè)處理沒(méi)返回值的情況。

    • 第三個(gè)和第四個(gè)重載形式繼承于std::_Function_base::_Ref_manager,可以看出它們基本上算是前兩個(gè)類的偏特化版本,當(dāng)?shù)诙€(gè)模板參數(shù)為std::reference_wrapper包裝的引用時(shí),就調(diào)用這兩個(gè)偏特化的版本。這兩個(gè)重載形式的唯一區(qū)別也是它們一個(gè)處理函數(shù)有返回值的情況,另一個(gè)處理沒(méi)返回值的情況?,F(xiàn)在問(wèn)題來(lái)了,為什么要搞一個(gè)對(duì)于std::reference_wrapper類型的偏特化版本呢?這是因?yàn)槿绻烧{(diào)用實(shí)體已經(jīng)先被std::reference_wrapper包裝過(guò)的話,那我們是絕對(duì)絕對(duì)不能直接調(diào)用這個(gè)可調(diào)用實(shí)體的,因?yàn)榇藭r(shí)根本不確定這個(gè)被包裝的可調(diào)用實(shí)體究竟是什么類型的,如果是類成員函數(shù)的話那當(dāng)然是不能直接調(diào)用的,此時(shí)必須使用std::mem_fn來(lái)獲取一個(gè)可調(diào)用的對(duì)象,類中使用的std::__callable_functor函數(shù)的實(shí)現(xiàn)如下面的代碼所示,可以看到有好幾種特化版本,當(dāng)std::reference_wrapper包裝的可調(diào)用實(shí)體是一個(gè)類成員函數(shù)指針時(shí),就會(huì)通過(guò)std::mem_fn來(lái)獲取一個(gè)可調(diào)用的對(duì)象,這和前面描述的內(nèi)容一致。

    template<typename _Functor>
    inline _Functor& __callable_functor(_Functor& __f)
    { return __f; }
    
    template<typename _Member, typename _Class>
    inline _Mem_fn<_Member _Class::*> __callable_functor(_Member _Class::* &__p)
    { return std::mem_fn(__p); }
    
    template<typename _Member, typename _Class>
    inline _Mem_fn<_Member _Class::*> __callable_functor(_Member _Class::* const &__p)
    { return std::mem_fn(__p); }
    
    template<typename _Member, typename _Class>
    inline _Mem_fn<_Member _Class::*> __callable_functor(_Member _Class::* volatile &__p)
    { return std::mem_fn(__p); }
    
    template<typename _Member, typename _Class>
    inline _Mem_fn<_Member _Class::*> __callable_functor(_Member _Class::* const volatile &__p)
    { return std::mem_fn(__p); }

    關(guān)于上面提到的std::reference_wrapper和std::mem_fn,大家如果可以不懂的話一定要看下面兩篇文章,不然的話就像學(xué)英語(yǔ)不會(huì)英語(yǔ)單詞一樣,根本不可能看懂std::function的內(nèi)容的

    《C++11的std::ref、std::cref源碼解析》
    《C++11的std::mem_fn源碼解析》

    • 第五個(gè)和第六個(gè)重載形式和前面的差不多,這兩個(gè)也是屬于偏特化版本,主要是用于處理可調(diào)用實(shí)體為類成員函數(shù)指針的情況,這里就可以看到直接調(diào)用了std::men_fn函數(shù)來(lái)使得我們可以直接調(diào)用對(duì)應(yīng)的類成員函數(shù),從這點(diǎn)也可以看出std::men_fn函數(shù)的重要性,不懂的小伙伴一定要去看前面兩篇文章啊。

    • 每一個(gè)類里面的_M_invoke函數(shù)都用了_M_get_pointer(來(lái)源不全部相同),從代碼邏輯上不難看出_M_get_pointer函數(shù)的作用是從第一個(gè)傳入?yún)?shù)__functor中取出對(duì)應(yīng)的可調(diào)用實(shí)體,然后將后面的可變參傳給這個(gè)可調(diào)用實(shí)體,運(yùn)行它,這個(gè)功能是不是就有點(diǎn)似曾相識(shí)了?對(duì),這就是我們平時(shí)正常調(diào)用函數(shù)的那樣子嘛,也就是說(shuō)std::function的函數(shù)執(zhí)行功能在這里實(shí)現(xiàn)了

    • 從代碼中我們可以看出這幾個(gè)類都是和std::_Function_base相關(guān)的,并且到現(xiàn)在還是不知道_M_functor究竟是個(gè)什么東西,接下來(lái)分析std::_Function_base,看一下里面究竟做了哪些工作

    3.3、_Any_data解析

    _Any_data位于libstdc++-v3\include\std\functional中

    union _Nocopy_types
    {
        void*       _M_object;
        const void* _M_const_object;
        void (*_M_function_pointer)();
        void (_Undefined_class::*_M_member_pointer)();
    };
    
    union _Any_data
    {
        void*       _M_access()       { return &_M_pod_data[0]; }
        const void* _M_access() const { return &_M_pod_data[0]; }
    
        template<typename _Tp>
        _Tp& _M_access()
        { return *static_cast<_Tp*>(_M_access()); }
    
        template<typename _Tp>
        const _Tp& _M_access() const
        { return *static_cast<const _Tp*>(_M_access()); }
    
        _Nocopy_types _M_unused;
        char _M_pod_data[sizeof(_Nocopy_types)];
    };

    看std::_Function_base之前先看一個(gè)重要的聯(lián)合體_Any_data,這個(gè)在前面出現(xiàn)很多次了,但是一直沒(méi)有介紹一下它究竟是個(gè)什么東西,下面簡(jiǎn)單分析一下:

    • 有兩個(gè)聯(lián)合體成員,一個(gè)是_M_unused(沒(méi)卵用),一個(gè)是_M_pod_data,這兩個(gè)的占用內(nèi)存是一樣的,具體原因就不講了,大家可以自己用sizeof去試一下

    • 里面有四個(gè)_M_access函數(shù),前兩個(gè)是直接將_M_pod_data的地址返回出去,不做任何轉(zhuǎn)換,后兩個(gè)則是可以將_M_pod_data轉(zhuǎn)換為任意類型返回,從這里可以看出這個(gè)_Any_data的作用就是來(lái)接管可調(diào)用對(duì)象的,所以后續(xù)可以通過(guò)各種轉(zhuǎn)換將它還原為可調(diào)用的形式(比如前面提到的那個(gè)_Function_base::_Base_manager<_Functor>::_M_get_pointer方法就是干這個(gè)貨活的)

    • 簡(jiǎn)單看一下_Nocopy_types這個(gè)聯(lián)合體,前兩個(gè)成員的寓意就是類實(shí)例或Lambda表達(dá)式,第三個(gè)寓意是普通函數(shù)指針,第四個(gè)寓意是類成員函數(shù)指針,仔細(xì)一看這不就是我們前面提到無(wú)數(shù)次的可調(diào)用實(shí)體的幾種形式嗎?這個(gè)_Nocopy_types從上下文看來(lái)并沒(méi)有什么亂用,估計(jì)就是源碼作者寫給讀者看的吧,讓大家更容易讀懂源碼。

    3.4、std::_Function_base解析

    std::_Function_base的實(shí)現(xiàn)位于libstdc++-v3\include\std\functional中

    class _Function_base
    {
    public:
        static const std::size_t _M_max_size = sizeof(_Nocopy_types);
        static const std::size_t _M_max_align = __alignof__(_Nocopy_types);
    
        template<typename _Functor>
        class _Base_manager
        {
        protected:
            static const bool __stored_locally =
                (__is_location_invariant<_Functor>::value
                && sizeof(_Functor) <= _M_max_size
                && __alignof__(_Functor) <= _M_max_align
                && (_M_max_align % __alignof__(_Functor) == 0));
    
            typedef integral_constant<bool, __stored_locally> _Local_storage;
    
            static _Functor* _M_get_pointer(const _Any_data& __source)
            {
                const _Functor* __ptr = __stored_locally? std::__addressof(__source._M_access<_Functor>()) : __source._M_access<_Functor*>();
                return const_cast<_Functor*>(__ptr);
            }
    
            static void _M_clone(_Any_data& __dest, const _Any_data& __source, true_type)
            {
                new (__dest._M_access()) _Functor(__source._M_access<_Functor>());
            }
    
            static void _M_clone(_Any_data& __dest, const _Any_data& __source, false_type)
            {
                __dest._M_access<_Functor*>() = new _Functor(*__source._M_access<_Functor*>());
            }
    
            static void _M_destroy(_Any_data& __victim, true_type)
            {
                __victim._M_access<_Functor>().~_Functor();
            }
    
            static void _M_destroy(_Any_data& __victim, false_type)
            {
                delete __victim._M_access<_Functor*>();
            }
    
        public:
            static bool _M_manager(_Any_data& __dest, const _Any_data& __source, _Manager_operation __op)
            {
                switch (__op)
                {
                    case __get_functor_ptr:
                        __dest._M_access<_Functor*>() = _M_get_pointer(__source);
                        break;
    
                    case __clone_functor:
                        _M_clone(__dest, __source, _Local_storage());
                        break;
    
                    case __destroy_functor:
                        _M_destroy(__dest, _Local_storage());
                        break;
                }
                return false;
            }
    
            static void _M_init_functor(_Any_data& __functor, _Functor&& __f)
            { _M_init_functor(__functor, std::move(__f), _Local_storage()); }
    
            template<typename _Signature>
            static bool _M_not_empty_function(const function<_Signature>& __f)
            { return static_cast<bool>(__f); }
    
            template<typename _Tp>
            static bool _M_not_empty_function(_Tp* const& __fp)
            { return __fp; }
    
            template<typename _Class, typename _Tp>
            static bool _M_not_empty_function(_Tp _Class::* const& __mp)
            { return __mp; }
    
            template<typename _Tp>
            static bool _M_not_empty_function(const _Tp&)
            { return true; }
    
        private:
            static void _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type)
            { new (__functor._M_access()) _Functor(std::move(__f)); }
    
            static void _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type)
            { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); }
        };
    
        template<typename _Functor>
        class _Ref_manager : public _Base_manager<_Functor*>
        {
            typedef _Function_base::_Base_manager<_Functor*> _Base;
    
        public:
            static bool _M_manager(_Any_data& __dest, const _Any_data& __source, _Manager_operation __op)
            {
                switch (__op)
                {
                    case __get_functor_ptr:
                        __dest._M_access<_Functor*>() = *_Base::_M_get_pointer(__source);
                        return is_const<_Functor>::value;
                        break;
    
                    default:
                        _Base::_M_manager(__dest, __source, __op);
                }
                return false;
            }
    
            static void _M_init_functor(_Any_data& __functor, reference_wrapper<_Functor> __f)
            {
                _Base::_M_init_functor(__functor, std::__addressof(__f.get()));
            }
        };
    
        _Function_base() : _M_manager(0) { }
    
        ~_Function_base()
        {
            if (_M_manager)
                _M_manager(_M_functor, _M_functor, __destroy_functor);
        }
    
        bool _M_empty() const { return !_M_manager; }
    
        typedef bool (*_Manager_type)(_Any_data&, const _Any_data&, _Manager_operation);
    
        _Any_data     _M_functor;
        _Manager_type _M_manager;
    };

    從源代碼中可以看出以下幾點(diǎn)信息:

    • 該類有兩個(gè)類成員,分別是_M_functor和_M_manager,_M_functor就不用多說(shuō)了,前面一直有提到它,他的類型_Any_data也在上一小節(jié)講過(guò)了。而_M_manager則是一個(gè)函數(shù)指針,下面再介紹它有什么用。

    • 這里看一下_Function_base::_Base_manager類里面的各個(gè)方法

      • _M_init_functor函數(shù):該函數(shù)前面提到過(guò)了,當(dāng)時(shí)看到的是將std::function接管的可調(diào)用對(duì)象傳遞給了這個(gè)函數(shù),而從前面我們知道_Any_data類型的數(shù)據(jù)是可以接管所有形式的可調(diào)用實(shí)體的,所以綜合可得_M_init_functor函數(shù)的作用就是將傳遞給它的第二個(gè)參數(shù)儲(chǔ)存到第一個(gè)參數(shù)中(_Any_data類型數(shù)據(jù)),這樣就達(dá)成了接管可調(diào)用實(shí)體的功能了

      • _M_get_pointer函數(shù):這個(gè)函數(shù)同樣在前面提到過(guò),當(dāng)時(shí)我們只知道通過(guò)調(diào)用_M_get_pointer可以獲取到我們接管的那個(gè)可調(diào)用實(shí)體,但是不知道是如何實(shí)現(xiàn)的,這里可以看出他的實(shí)現(xiàn)是非常簡(jiǎn)單的,也就是從它的傳入?yún)?shù)(_Any_data類型數(shù)據(jù))將可調(diào)用實(shí)體取出,并強(qiáng)制轉(zhuǎn)換為合法的類型,里面用到了std::__addressof,作用就是即使目標(biāo)變量(類)存在operator&的重載,也依然能夠獲得變量的地址。

      • 關(guān)于std::__addressof的詳細(xì)內(nèi)容可以看這篇文章《C++11的std::addressof源碼解析》

      • _M_manager函數(shù):該函數(shù)就是根據(jù)傳入的第三個(gè)參數(shù)來(lái)確定執(zhí)行不同的功能,其余的幾個(gè)函數(shù)無(wú)非就是涉及到內(nèi)存的分配和釋放之類的,對(duì)我們理解std::function的影響不大,這里就不展開講了

    • 接下來(lái)看一下_Function_base::_Ref_manager類

      • 可以看到該類繼承于_Function_base::_Base_manager類,可見他擁有_Function_base::_Base_manager類實(shí)現(xiàn)的所有功能

      • 該類是處理當(dāng)std::function接管的是一個(gè)引用包裝類的情況的,為什么這種情況需要單獨(dú)處理呢?因?yàn)榇藭r(shí)如果直接對(duì)傳入?yún)?shù)取地址,取到的將是引用包裝類的地址,而不是我們要接管的可調(diào)用對(duì)象的地址,所以只能搞這么一個(gè)特化版本,就像_Function_base::_Ref_manager類做的那樣,里面的_M_init_functor函數(shù)通過(guò)使用reference_wrapper的get方法獲取到了std::function接管的可調(diào)用對(duì)象的真實(shí)地址

    • _Function_base類里的其它方法就不講了,大家自己看一下吧,其余的實(shí)現(xiàn)基本都是基于前面講的那些內(nèi)容,比較簡(jiǎn)單

    4、總結(jié)

    本文先是簡(jiǎn)單介紹了std::function的用途(對(duì)C++中各種可調(diào)用實(shí)體進(jìn)行封裝),然后通過(guò)對(duì)源碼進(jìn)行詳細(xì)分析,我們知道了std::function是如何實(shí)現(xiàn)對(duì)可調(diào)用實(shí)體進(jìn)行封裝的,源碼內(nèi)容會(huì)比較復(fù)雜,但是其中的設(shè)計(jì)思路是很值得我們學(xué)習(xí)借鑒的,尤其是與std::reference_wrapper和std::mem_fn配合的那部分代碼更是精妙絕倫。

    到此,相信大家對(duì)“C++11中std::function的用法”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI