国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

C++ function技術的實現與具體運用

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

掃碼添加小助手

加入工程師交流群

【導讀】:本文主要講解C++ function技術的實現與具體運用。

std::function是一個函數對象的包裝器,std::function的實例可以存儲,復制和調用任何可調用的目標,包括:

函數。

lamada表達式。

綁定表達式或其他函數對象。

指向成員函數和指向數據成員的指針。

當std::function對象沒有初始化任何實際的可調用元素,調用std::function對象將拋出std::bad_function_call異常。

本文我們來談一下std::function的實現原理。

1. std::function簡介

在討論其原理的時候,我們來熟悉一下這個東西是怎么使用的,C++標準庫詳細說明了這個的基本使用http://www.cplusplus.com/reference/functional/function/.

這里我們大概總結一下。

1.1 Member types

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

1.2 Member functions

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

1.3 基本使用

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

從上面我們可以發現,std::function可以表示函數,lamada,可調用類對象。

2. std::function實現

在標準庫中STL設計為如下:

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繼承關系比較簡單,主要使用

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

這個來存儲我們設置的可調用對象,我們從std::function的使用過程看一下整個原理。

2.1 函數對象賦值

我們使用的時候一般使用f = Caller;來設置函數對象,我們看下這個的實現過程。

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

我們看this->_Reset(_Func)這個函數,因為這個才是設置函數可調用對象的東西。

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()); }

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

設置之后,我們看下調用操作怎么完成。

2.2 operator() 的實現

調用操作主要是通過operator()來實現的,我們看下這個的實現過程。

_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...>轉發了調用操作_Do_call

2.3 _Func_impl的實現

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這個類通過_Do_call來轉發函數對象的調用操作。

3. 總結

這里我們看下std::function的結構信息,如下:

330d8784-5788-11eb-8b86-12bb97331649.png

從這里我們發現_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; }

內存結構如下:

333686e8-5788-11eb-8b86-12bb97331649.png

由此我們可以發現std::function是利用一個_Compressed_pair<_Alloc, _Callable> _Mypair;拷貝了元素的數據信息。

主要的初始化過程為:

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的類型,這個聲明如下(也就是去掉引用和其他屬性信息):

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的原理分析了,希望在后續的使用中,我們能夠知道std::function在什么情況下可以使用,以及背后完成的事情。

責任編輯:lq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 函數
    +關注

    關注

    3

    文章

    4417

    瀏覽量

    67501
  • C++
    C++
    +關注

    關注

    22

    文章

    2123

    瀏覽量

    77110
  • 初始化
    +關注

    關注

    0

    文章

    52

    瀏覽量

    12372

原文標題:C++ std::function 技術淺談

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

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

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    keil實現cc++混合編程

    參考touchgfx生成的代碼,發現了一個不需要添加--cpp11 參數的解決方法,具體操作如下。 一、創建一個空白的C文件和頭文件在頭文件中定義c++文件中需要調用的函數,如圖所示 二、在
    發表于 01-26 08:58

    C語言與C++的區別及聯系

    缺點:性能比面向過程低。 二、具體語言上的區別 1、關鍵字的不同 C語言有32個關鍵字;C++有63個關鍵字。 2、后綴名不同 C源文件后綴.
    發表于 12-24 07:23

    CC++之間的聯系

    1、語法兼容性: C++完全兼容C語言的語法,這意味著任何有效的C語言程序都可以直接在C++編譯器下編譯通過。 2、底層控制: C++
    發表于 12-11 06:51

    C語言和C++之間的區別是什么

    區別 1、面向對象編程 (OOP): C語言是一種面向過程的語言,它強調的是通過函數將任務分解為一系列步驟進行執行。 C++C語言的基礎上擴展了面向對象的特性,支持類(class)、封裝、繼承
    發表于 12-11 06:23

    C++之父親臨北京,AI原生時代最值得參加的系統軟件技術大會日程發布

    秉承"全球專家、卓越智慧"的理念,由 CSDN 與奇點智能研究院舉辦的「2025 全球 C++ 及系統軟件技術大會」將于 12 月 12-13 日在北京金隅喜來登大酒店正式舉辦。
    的頭像 發表于 12-05 15:47 ?339次閱讀

    C/C++條件編譯

    條件編譯是一種在編譯時根據條件選擇性地包含或排除部分代碼的處理方法。在 C/C++ 中,條件編譯使用預處理指令 #ifdef、#endif、#else 和 #elif 來實現。常用的條件編譯指令有
    發表于 12-05 06:21

    C++程序異常的處理機制

    1、什么是異常處理? 有經驗的朋友應該知道,在正常的CC++編程過程中難免會碰到程序不按照原本設計運行的情況。 最常見的有除法分母為零,數組越界,內存分配失效、打開相應文件失敗等等。 一個程序
    發表于 12-02 07:12

    C/C++代碼靜態測試工具Perforce QAC 2025.3的新特性

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

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

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

    C++ 與 Python:樹莓派上哪種語言更優?

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

    Perforce QAC產品簡介:面向C/C++的靜態代碼分析工具(已通過SO 26262認證)

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

    基于LockAI視覺識別模塊:C++目標檢測

    本文檔基于瑞芯微RV1106的LockAI凌智視覺識別模塊,通過C++語言做的目標檢測實驗。本文檔展示了如何使用lockzhiner_vision_module::PaddleDet類進行目標檢測,并通過lockzhiner_vision_module::Visualize函數將檢測結果可視
    的頭像 發表于 06-06 13:56 ?839次閱讀
    基于LockAI視覺識別模塊:<b class='flag-5'>C++</b>目標檢測

    主流的 MCU 開發語言為什么是 C 而不是 C++

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

    C++學到什么程度可以找工作?

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

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

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