亚洲精品久久久久久久久久久,亚洲国产精品一区二区制服,亚洲精品午夜精品,国产成人精品综合在线观看,最近2019中文字幕一页二页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

講解C++ function 技術(shù)的實(shí)現(xiàn)與具體運(yùn)用

Linux愛好者 ? 來源:xdesk ? 作者:xdesk ? 2021-01-19 17:05 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

【導(dǎo)讀】:本文主要講解 C++ function 技術(shù)的實(shí)現(xiàn)與具體運(yùn)用。

std::function是一個(gè)函數(shù)對象的包裝器,std::function的實(shí)例可以存儲,復(fù)制和調(diào)用任何可調(diào)用的目標(biāo),包括:

函數(shù)。

lamada表達(dá)式。

綁定表達(dá)式或其他函數(shù)對象。

指向成員函數(shù)和指向數(shù)據(jù)成員的指針。

當(dāng)std::function對象沒有初始化任何實(shí)際的可調(diào)用元素,調(diào)用std::function對象將拋出std::bad_function_call異常。

本文我們來談一下std::function的實(shí)現(xiàn)原理。

1. std::function簡介

在討論其原理的時(shí)候,我們來熟悉一下這個(gè)東西是怎么使用的,C++標(biāo)準(zhǔn)庫詳細(xì)說明了這個(gè)的基本使用http://www.cplusplus.com/reference/functional/function/.

這里我們大概總結(jié)一下。

1.1 Member types

result_type 返回類型
argument_type 如果函數(shù)對象只有一個(gè)參數(shù),那么這個(gè)代表參數(shù)類型。
first_argument_type 如果函數(shù)對象有兩個(gè)個(gè)參數(shù),那么這個(gè)代表第一個(gè)參數(shù)類型。
second_argument_type 如果函數(shù)對象有兩個(gè)個(gè)參數(shù),那么這個(gè)代表第二個(gè)參數(shù)類型。
成員類型 說明

1.2 Member functions

constructor 構(gòu)造函數(shù):constructs a new std::function instance
destructor 析構(gòu)函數(shù):destroys a std::function instance
operator= 給定義的function對象賦值
operator bool 檢查定義的function對象是否包含一個(gè)有效的對象
operator() 調(diào)用一個(gè)對象
成員函數(shù)聲明 說明

1.3 基本使用

#include #include intfun(inta,intb,intc,intd) { std::cout<f; f=[](inta,intb,intc,intd)->int { std::cout<

從上面我們可以發(fā)現(xiàn),std::function可以表示函數(shù),lamada,可調(diào)用類對象。

2. std::function實(shí)現(xiàn)

在標(biāo)準(zhǔn)庫中STL設(shè)計(jì)為如下:

template struct_Arg_types {//provideargument_type,etc.(sometimes) }; template struct_Arg_types<_Ty1> {//provideargument_type,etc.(sometimes) typedef_Ty1argument_type; }; template struct_Arg_types<_Ty1,?_Ty2> {//provideargument_type,etc.(sometimes) typedef_Ty1first_argument_type; typedef_Ty2second_argument_type; }; template class_Func_class :public_Arg_types<_Types...> {//implementfunctiontemplate public: typedef_Retresult_type; typedef_Func_class<_Ret,?_Types...>_Myt; typedef_Func_base<_Ret,?_Types...>_Ptrt; private: bool_Local()const_NOEXCEPT {//testforlocallystoredcopyofobject return(_Getimpl()==_Getspace()); } union_Storage {//storageforsmallobjects(basic_stringissmall) max_align_t_Dummy1;//formaximumalignment char_Dummy2[_Space_size];//topermitaliasing _Ptrt*_Ptrs[_Num_ptrs];//_Ptrs[_Num_ptrs-1]isreserved }; _Storage_Mystorage; }; template struct_Get_function_impl<_Ret?CALL_OPT?(_Types...)> {/*determinetypefromargumentlist*/ typedef_Func_class<_Ret,?_Types...>type; }; template classfunction :public_Get_function_impl<_Fty>::type {//wrapperforcallableobjects public: typedeffunction<_Fty>_Myt; };

上面的std::function繼承關(guān)系比較簡單,主要使用

union_Storage { //storageforsmallobjects(basic_stringissmall) max_align_t_Dummy1;//formaximumalignment char_Dummy2[_Space_size];//topermitaliasing _Ptrt*_Ptrs[_Num_ptrs];//_Ptrs[_Num_ptrs-1]isreserved };

這個(gè)來存儲我們設(shè)置的可調(diào)用對象,我們從std::function的使用過程看一下整個(gè)原理。

2.1 函數(shù)對象賦值

我們使用的時(shí)候一般使用f = Caller;來設(shè)置函數(shù)對象,我們看下這個(gè)的實(shí)現(xiàn)過程。

template _Myt&operator=(reference_wrapper<_Fx>_Func)_NOEXCEPT { //assignwrapperholdingreference_wrappertofunctionobject this->_Tidy(); this->_Reset(_Func); return(*this); }

我們看this->_Reset(_Func)這個(gè)函數(shù),因?yàn)檫@個(gè)才是設(shè)置函數(shù)可調(diào)用對象的東西。

void_Set(_Ptrt*_Ptr)_NOEXCEPT {//storepointertoobject _Mystorage._Ptrs[_Num_ptrs-1]=_Ptr; } void_Reset_impl(_Fx&&_Val,const_Alloc&_Ax, _Myimpl*,_Alimpl&_Al,false_type) {//storecopyof_Valwithallocator,small(locallystored) _Myimpl*_Ptr=static_cast<_Myimpl?*>(_Getspace()); _Al.construct(_Ptr,_STDforward<_Fx>(_Val),_Ax); _Set(_Ptr); } template void_Reset_alloc(_Fx&&_Val,const_Alloc&_Ax) {//storecopyof_Valwithallocator if(!_Test_callable(_Val)) {//nullmemberpointer/functionpointer/std::function return;//alreadyempty } typedeftypenamedecay<_Fx>::type_Decayed; typedef_Func_impl<_Decayed,?_Alloc,?_Ret,?_Types...>_Myimpl; _Myimpl*_Ptr=0; typedef_Wrap_alloc<_Alloc>_Alimpl0; typedeftypename_Alimpl0::templaterebind<_Myimpl>::other_Alimpl; _Alimpl_Al(_Ax); _Reset_impl(_STDforward<_Fx>(_Val),_Ax, _Ptr,_Al,_Is_large<_Myimpl>()); } template void_Reset(_Fx&&_Val) { //storecopyof_Val _Reset_alloc(_STDforward<_Fx>(_Val),allocator()); }

這個(gè)代碼的主要意思就是創(chuàng)建一個(gè)_Func_impl<_Decayed, _Alloc, _Ret, _Types...>指針,然后賦值_Mystorage._Ptrs[_Num_ptrs - 1] = _Ptr;。

設(shè)置之后,我們看下調(diào)用操作怎么完成。

2.2 operator() 的實(shí)現(xiàn)

調(diào)用操作主要是通過operator()來實(shí)現(xiàn)的,我們看下這個(gè)的實(shí)現(xiàn)過程。

_Ptrt*_Getimpl()const_NOEXCEPT {//getpointertoobject return(_Mystorage._Ptrs[_Num_ptrs-1]); } _Retoperator()(_Types..._Args)const {//callthroughstoredobject if(_Empty()) _Xbad_function_call(); return(_Getimpl()->_Do_call(_STDforward<_Types>(_Args)...)); }

因此,我們是通過_Func_impl<_Decayed, _Alloc, _Ret, _Types...>轉(zhuǎn)發(fā)了調(diào)用操作_Do_call

2.3 _Func_impl的實(shí)現(xiàn)

class_Func_impl :public_Func_base<_Rx,?_Types...> {//derivedclassforspecificimplementationtypes public: typedef_Func_impl<_Callable,?_Alloc,?_Rx,?_Types...>_Myt; typedef_Func_base<_Rx,?_Types...>_Mybase; typedef_Wrap_alloc<_Alloc>_Myalty0; typedeftypename_Myalty0::templaterebind<_Myt>::other_Myalty; typedefis_nothrow_move_constructible<_Callable>_Nothrow_move; virtual_Rx_Do_call(_Types&&..._Args) {//callwrappedfunction return(_Invoke_ret(_Forced<_Rx>(),_Callee(), _STDforward<_Types>(_Args)...)); } _Compressed_pair<_Alloc,?_Callable>_Mypair; };

_Func_impl這個(gè)類通過_Do_call來轉(zhuǎn)發(fā)函數(shù)對象的調(diào)用操作。

3. 總結(jié)

這里我們看下std::function的結(jié)構(gòu)信息,如下:

從這里我們發(fā)現(xiàn)_Storage大小為:

constint_Num_ptrs=6+16/sizeof(void*); constsize_t_Space_size=(_Num_ptrs-1)*sizeof(void*);

_Num_ptrs值為10。

如果我們賦值的對象有成員變量會是什么情況呢?例如如下:

classCCaller { public: intoperator()(inta,intb,intc,intd) { std::cout<f; f=Caller; f(10,20,30,40); return0; }

內(nèi)存結(jié)構(gòu)如下:

由此我們可以發(fā)現(xiàn)std::function是利用一個(gè)_Compressed_pair<_Alloc, _Callable> _Mypair;拷貝了元素的數(shù)據(jù)信息。

主要的初始化過程為:

emplate void_Reset_alloc(_Fx&&_Val,const_Alloc&_Ax) {//storecopyof_Valwithallocator if(!_Test_callable(_Val)) {//nullmemberpointer/functionpointer/std::function return;//alreadyempty } typedeftypenamedecay<_Fx>::type_Decayed; typedef_Func_impl<_Decayed,?_Alloc,?_Ret,?_Types...>_Myimpl; _Myimpl*_Ptr=0; typedef_Wrap_alloc<_Alloc>_Alimpl0; typedeftypename_Alimpl0::templaterebind<_Myimpl>::other_Alimpl; _Alimpl_Al(_Ax); _Reset_impl(_STDforward<_Fx>(_Val),_Ax, _Ptr,_Al,_Is_large<_Myimpl>()); }

其中decay<_Fx>::type定義了_Compressed_pair<_Alloc, _Callable> _Mypair;中_Callable的類型,這個(gè)聲明如下(也就是去掉引用和其他屬性信息):

template structdecay {//determinesdecayedversionof_Ty typedeftypenameremove_reference<_Ty>::type_Ty1; typedeftypename_If::value, typenameremove_extent<_Ty1>::type*, typename_If::value, typenameadd_pointer<_Ty1>::type, typenameremove_cv<_Ty1>::type>::type>::typetype; };

至此,我們大致上完成了std::function的原理分析了,希望在后續(xù)的使用中,我們能夠知道std::function在什么情況下可以使用,以及背后完成的事情。

責(zé)任編輯:lq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4404

    瀏覽量

    66640
  • C++
    C++
    +關(guān)注

    關(guān)注

    22

    文章

    2120

    瀏覽量

    76632

原文標(biāo)題:C++ std::function 技術(shù)淺談

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    C/C++代碼靜態(tài)測試工具Perforce QAC 2025.3的新特性

    ?Perforce Validate?中?QAC?項(xiàng)目的相對/根路徑的支持。C++?分析也得到了增強(qiáng),增加了用于檢測 C++?并發(fā)問題的新檢查,并改進(jìn)了實(shí)體名稱和實(shí)
    的頭像 發(fā)表于 10-13 18:11 ?200次閱讀
    <b class='flag-5'>C</b>/<b class='flag-5'>C++</b>代碼靜態(tài)測試工具Perforce QAC 2025.3的新特性

    技能+1!如何在樹莓派上使用C++控制GPIO?

    在使用樹莓派時(shí),你會發(fā)現(xiàn)Python和Scratch是許多任務(wù)(包括GPIO編程)中最常用的編程語言。但你知道嗎,你也可以使用C++進(jìn)行GPIO編程,而且這樣做還有不少好處。借助WiringPi
    的頭像 發(fā)表于 08-06 15:33 ?3327次閱讀
    技能+1!如何在樹莓派上使用<b class='flag-5'>C++</b>控制GPIO?

    C++ 與 Python:樹莓派上哪種語言更優(yōu)?

    Python是樹莓派上的首選編程語言,我們的大部分教程都使用它。然而,C++在物聯(lián)網(wǎng)項(xiàng)目中同樣廣受歡迎且功能強(qiáng)大。那么,在樹莓派項(xiàng)目中選擇哪種語言更合適呢?Python因其簡潔性、豐富的庫和資源而被
    的頭像 發(fā)表于 07-24 15:32 ?558次閱讀
    <b class='flag-5'>C++</b> 與 Python:樹莓派上哪種語言更優(yōu)?

    Perforce QAC產(chǎn)品簡介:面向C/C++的靜態(tài)代碼分析工具(已通過SO 26262認(rèn)證)

    Perforce QAC專為C/C++開發(fā)者打造,支持多種編碼規(guī)范、功能安全標(biāo)準(zhǔn)(ISO 26262)等,廣泛用于汽車、醫(yī)療、嵌入式開發(fā)領(lǐng)域,可幫助快速識別關(guān)鍵缺陷、提升代碼質(zhì)量、實(shí)現(xiàn)合規(guī)交付。
    的頭像 發(fā)表于 07-10 15:57 ?696次閱讀
    Perforce QAC產(chǎn)品簡介:面向<b class='flag-5'>C</b>/<b class='flag-5'>C++</b>的靜態(tài)代碼分析工具(已通過SO 26262認(rèn)證)

    主流的 MCU 開發(fā)語言為什么是 C 而不是 C++?

    在單片機(jī)的地界兒里,C語言穩(wěn)坐中軍帳,C++想分杯羹?難嘍。咱電子工程師天天跟那針尖大的內(nèi)存空間較勁,C++那些花里胡哨的玩意兒,在這兒真玩不轉(zhuǎn)。先說內(nèi)存這道坎兒。您當(dāng)stm32f4的256kRAM
    的頭像 發(fā)表于 05-21 10:33 ?736次閱讀
    主流的 MCU 開發(fā)語言為什么是 <b class='flag-5'>C</b> 而不是 <b class='flag-5'>C++</b>?

    C++學(xué)到什么程度可以找工作?

    C++學(xué)到什么程度可以找工作?要使用C++找到工作,特別是作為軟件開發(fā)人員或相關(guān)職位,通常需要掌握以下幾個(gè)方面: 1. **語言基礎(chǔ)**:你需要對C++的核心概念有扎實(shí)的理解,包括但不限于指針、內(nèi)存
    發(fā)表于 03-13 10:19

    創(chuàng)建了用于OpenVINO?推理的自定義C++和Python代碼,從C++代碼中獲得的結(jié)果與Python代碼不同是為什么?

    創(chuàng)建了用于OpenVINO?推理的自定義 C++ 和 Python* 代碼。 在兩個(gè)推理過程中使用相同的圖像和模型。 從 C++ 代碼中獲得的結(jié)果與 Python* 代碼不同。
    發(fā)表于 03-06 06:22

    源代碼加密、源代碼防泄漏c/c++與git服務(wù)器開發(fā)環(huán)境

    源代碼加密對于很多研發(fā)性單位來說是至關(guān)重要的,當(dāng)然每家企業(yè)的業(yè)務(wù)需求不同所用的開發(fā)環(huán)境及開發(fā)語言也不盡相同,今天主要來講一下c++及git開發(fā)環(huán)境的源代碼防泄密保護(hù)方案。企業(yè)源代碼泄密場景一、在很多
    的頭像 發(fā)表于 02-12 15:26 ?776次閱讀
    源代碼加密、源代碼防泄漏<b class='flag-5'>c</b>/<b class='flag-5'>c++</b>與git服務(wù)器開發(fā)環(huán)境

    基于OpenHarmony標(biāo)準(zhǔn)系統(tǒng)的C++公共基礎(chǔ)類庫案例:ThreadPoll

    1、程序簡介該程序是基于OpenHarmony標(biāo)準(zhǔn)系統(tǒng)的C++公共基礎(chǔ)類庫的線程池處理:ThreadPoll。本案例完成如下工作:創(chuàng)建1個(gè)線程池,設(shè)置該線程池內(nèi)部有1024個(gè)線程空間。啟動(dòng)5個(gè)線程
    的頭像 發(fā)表于 02-10 18:09 ?553次閱讀
    基于OpenHarmony標(biāo)準(zhǔn)系統(tǒng)的<b class='flag-5'>C++</b>公共基礎(chǔ)類庫案例:ThreadPoll

    Spire.XLS for C++組件說明

    Spire.XLS for C++ 是一款專業(yè)的 C++ Excel 組件,可以用在各種 C++ 框架和應(yīng)用程序中。Spire.XLS for C++ 提供了一個(gè)對象模型 Excel
    的頭像 發(fā)表于 01-14 09:40 ?1255次閱讀
    Spire.XLS for <b class='flag-5'>C++</b>組件說明

    EE-112:模擬C++中的類實(shí)現(xiàn)

    電子發(fā)燒友網(wǎng)站提供《EE-112:模擬C++中的類實(shí)現(xiàn).pdf》資料免費(fèi)下載
    發(fā)表于 01-03 15:15 ?0次下載
    EE-112:模擬<b class='flag-5'>C++</b>中的類<b class='flag-5'>實(shí)現(xiàn)</b>

    AKI跨語言調(diào)用庫神助攻C/C++代碼遷移至HarmonyOS NEXT

    )開發(fā)框架。它極大地簡化了JS與C/C++之間的跨語言訪問,為開發(fā)者提供了一種邊界性編程體驗(yàn)友好的解決方案。通過AKI,開發(fā)者可以使用讓代碼更易讀的語法糖,實(shí)現(xiàn)JS與C/
    發(fā)表于 01-02 17:08

    運(yùn)動(dòng)控制卡周期上報(bào)實(shí)時(shí)數(shù)據(jù)IO狀態(tài)之C++

    使用C++進(jìn)行運(yùn)動(dòng)控制卡的周期上報(bào)功能實(shí)現(xiàn)
    的頭像 發(fā)表于 12-17 13:59 ?1405次閱讀
    運(yùn)動(dòng)控制卡周期上報(bào)實(shí)時(shí)數(shù)據(jù)IO狀態(tài)之<b class='flag-5'>C++</b>篇

    同樣是函數(shù),在CC++中有什么區(qū)別

    同樣是函數(shù),在 CC++ 中有什么區(qū)別? 第一個(gè)返回值。 C語言的函數(shù)可以不寫返回值類型,編譯器會默認(rèn)為返回 int。 但是 C++ 的函數(shù),除了構(gòu)造和析構(gòu)這兩個(gè)特殊的函數(shù),必須
    的頭像 發(fā)表于 11-29 10:25 ?1203次閱讀

    C++新手容易犯的十個(gè)編程錯(cuò)誤

    簡單的總結(jié)一下?C++ 新手容易犯的一些編程錯(cuò)誤,給新人們提供一個(gè)參考。 1 有些關(guān)鍵字在 cpp 文件中多寫了 對于 C++ 類,一些關(guān)鍵字只要寫在 .h 中就好,cpp 中就不用再加上了,比如
    的頭像 發(fā)表于 11-15 12:42 ?1347次閱讀