色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

3天內不再提示

重點了解一下C++11 包裝器function

冬至子 ? 來源:iDoitnow ? 作者:艱默 ? 2023-07-18 16:41 ? 次閱讀

C++提供了多個包裝器,它們主要是為了給其他編程接口提供更一致或更合適的接口。C++11提供了多個包裝器,這里我們重點了解一下包裝器function

對于function, C++ 參考手冊給出的定義為:

類模板 std::function 是通用多態函數封裝器。std::function 的實例能存儲、復制及調用任何可調用 (Callable) 目標——函數、 lambda 表達式、 bind 表達式或其他函數對象,還有指向成員函數指針和指向數據成員指針。

C++11為什么要引入function

我們先看一個例子:

#include < iostream >

template < typename T, typename F >
T use_f(T v, F f) {
    static int count = 0;
    count++;
    std::cout < < " use_f count = " < < count < < ", &count = " < < &count
        < < std::endl;
    return f(v);
}

class Fp {
    private:
    double z_;

    public:
    Fp(double z = 1.0) : z_(z) {}
    double operator()(double p) { return z_ * p; }
};

class Fq {
    private:
    double z_;

    public:
    Fq(double z = 1.0) : z_(z) {}
    double operator()(double q) { return z_ + q; }
};

double dub(double x) { return 2.0 * x; }
double square(double x) { return x * x; }
int main() {
    using std::cout;
    using std::endl;
    double y = 1.21;
    cout < < "Function pointer dub:n";
    /*dub是函數名(函數名是一個指針),
    因此參數F對應的類型為double(*)double,
    即一個指向(接受一個double參數并返回一個double的)函數指針*/
    cout < < " " < < use_f(y, dub) < < endl; 
    cout < < "Function pointer square:n";
    cout < < " " < < use_f(y, square) < < endl;//同上
    
    cout < < "Function object Fp:n";
    //Fp(5.0)是一個參數對象,F對應的類型為Fp
    cout < < " " < < use_f(y, Fp(5.0)) < < endl;
    cout < < "Function object Fq:n";
    //Fq(5.0)是一個參數對象,F對應的類型為Fq
    cout < < " " < < use_f(y, Fq(5.0)) < < endl;
    
    cout < < "Lambda expression 1:n";
    //此處是一個lambda表達式,F對應的類型為該lambda表達式使用的類型
    cout < < " " < < use_f(y, [](double u) { return u * u; }) < < endl;
    cout < < "Lambda expression 2:n";
    ////此處是一個lambda表達式,F對應的類型為該lambda表達式使用的類型
    cout < < " " < < use_f(y, [](double u) { return u + u / 2.0; }) < < endl;
    return 0;
}

程序通過一個模板函數use_f使用參數f表示調用的類型,然后將f(v)返回。在主函數中我們6次調用模板函數,對于前兩個調用的use_f為同一個實例化。后面四個,每一個都有其對應use_f的實例化。實際上,上述代碼的運行結果如下:

Function pointer dub:
  use_f count = 1, &count = 0x555555756140
2.42
Function pointer square:
  use_f count = 2, &count = 0x555555756140
1.4641
Function object Fp:
  use_f count = 1, &count = 0x555555756144
6.05
Function object Fq:
  use_f count = 1, &count = 0x555555756148
6.21
Lambda expression 1:
  use_f count = 1, &count = 0x555555756138

從運行結果中,我們可以看出,在這六次調用中use_f的實例化了5次。使用模板函數,看似統一了操作形式,但其對于不同類型的F對模板函數都要進行一次實例化,這大大增加了編譯的時長,并使頭文件也增大,同時也降低了代碼的執行效率。為了解決這類問題,我們首先能想到的解決辦法就是:降低use_f的實例化的次數,理想的情況下是:在這6次循環調用的時候,調用同一個use_f的實例。針對上述例子,根據代碼注釋的分析,如果我們能將這6次調用中模板函數中F的類型保持統一,就可以像第一、二次調用的情況類似,使這六次調用同一個use_f的實例成為可能。

針對例子中的函數指針、函數對象和lambda表達式,它們有一個共同的特征:都是接受一個double參數并返回一個double值。也就是它們的調用特征標(它們的特征標都是double(double))相同。這便是function解決這個問題的關鍵。【 :調用特征標是由返回類型和參數類型列表決定的,其格式為:返回類型(參數類型列表),其中每個參數類型用逗號分隔。】

因此,C++11引入了function包裝器。function包裝器可以簡單理解為一個接口,它可以將特征標相同的函數指針、函數對象和lambda表達式等統一定義為一類特殊的對象。

function的用法

包裝器function的本質是一個模板,它是在頭文件functional中聲明,其使用方法如下:

template< class >
class function; 

template< class R, class... Args >
class function< R(Args...) >;

其中R為被調用函數的返回類型,Args為被調用函數的形參。存儲的可調用對象被稱為std::function的目標,如果目標為空,則調用空的function會導致拋出std::bad_function_call異常。

示例:

#include < functional >
#include < iostream >

void print_num(int i) { std::cout < < i < < 'n'; }

int main() {
  // 存儲自由函數
  std::function< void(int) > f_display = print_num;
  f_display(-9);

  // 存儲 lambda
  std::function< double(double) > f_dub = [](double a) { return 2.0 * a; };
  std::cout < < f_dub(2) < < 'n';

  // 存儲目標為空
  std::function< int() > f = nullptr;
  try {
    f();
  } catch (const std::bad_function_call& e) { //拋出異常
    std::cout < < e.what() < < 'n';
  }
}

輸出結果為:

-9
4
bad_function_call

在了解完function的用法之后,回到我們最開始的問題,其中,6次循環中要處理的目標的特征標均為double(double),因此,我們班使用function包裝器將它們將統一“包裝”成function類型,這樣模板函數use_f將只實例化一次。使用function包裝器改進后的代碼如下所示:

#include < functional >
#include < iostream >

template < typename T, typename F >
T use_f(T v, F f) {
  static int count = 0;
  count++;
  std::cout < < " use_f count = " < < count < < ", &count = " < < &count
            < < std::endl;
  return f(v);
}

class Fp {
 private:
  double z_;

 public:
  Fp(double z = 1.0) : z_(z) {}
  double operator()(double p) { return z_ * p; }
};

class Fq {
 private:
  double z_;

 public:
  Fq(double z = 1.0) : z_(z) {}
  double operator()(double q) { return z_ + q; }
};

double dub(double x) { return 2.0 * x; }
double square(double x) { return x * x; }
int main() {
  using std::cout;
  using std::endl;
  using std::function;
  double y = 1.21;
  typedef function< double(double) > fdd;  // simplify the type declaration

  cout < < "Function pointer dub:n";
  cout < < " " < < use_f(y, fdd(dub)) < < endl;
  cout < < "Function pointer square:n";
  cout < < " " < < use_f(y, fdd(square)) < < endl;
  cout < < "Function object Fp:n";
  cout < < " " < < use_f(y, fdd(Fq(10.0))) < < endl;
  cout < < "Function object Fq:n";
  cout < < " " < < use_f(y, fdd(Fp(10.0))) < < endl;
  cout < < "Lambda expression 1:n";
  cout < < " " < < use_f(y, fdd([](double u) { return u * u; })) < < endl;
  cout < < "Lambda expression 2:n";
  cout < < " " < < use_f< double >(y, fdd([](double u) { return u + u / 2.0; }))
       < < endl;

  return 0;
}

輸出結果為:

Function pointer dub:
  use_f count = 1, &count = 0x555555758134
2.42
Function pointer square:
  use_f count = 2, &count = 0x555555758134
1.4641
Function object Fp:
  use_f count = 3, &count = 0x555555758134
11.21
Function object Fq:
  use_f count = 4, &count = 0x555555758134
12.1
Lambda expression 1:
  use_f count = 5, &count = 0x555555758134
1.4641
Lambda expression 2:
  use_f count = 6, &count = 0x555555758134
1.815

從輸出結果可以看出,use_f確實只實例化了一次,增加了編碼效率,6次循環調用同一個函數,增加了代碼額執行效率。

總結

function包裝器將可調用對象的類型進行統一,便于我們對其進行統一化管理,同時,使用function包裝器可以解決模板效率低下,實例化多份的問題。

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

    關注

    38

    文章

    7484

    瀏覽量

    163763
  • C++語言
    +關注

    關注

    0

    文章

    147

    瀏覽量

    6989
  • 封裝器
    +關注

    關注

    0

    文章

    7

    瀏覽量

    5866
收藏 人收藏

    評論

    相關推薦

    使用C++11新特性實現個通用的線程池設計

    C++11標準之前,多線程編程只能使用pthread_xxx開頭的組POSIX標準的接口。從C++11標準開始,多線程相關接口封裝在了C++的std命名空間里。
    的頭像 發表于 12-22 13:58 ?1281次閱讀
    使用<b class='flag-5'>C++11</b>新特性實現<b class='flag-5'>一</b>個通用的線程池設計

    C++標準庫學習筆記重點

    新特性:1.C++98源碼編譯后二進制文件不能被C++11調用兼容,須在C++11重新編譯源碼。2.“在兩個template表達式的閉符之間放
    發表于 10-23 20:28

    如何在rt-thread的env環境中配置C++11

    1、rt-thread的env環境是否支持C++112、如何在rt-thread的env環境中配置C++11
    發表于 05-06 09:52

    基于C++11的輕量級對象間通信機制

    針對對象間跨線程或跨DLL通信時容易增加對象之間耦合度的現象,借鑒Action Script 3.0語言中事件模型以及PC機總線通信的思想,提出種基于C++11的輕量級對象間通信機制。在設計上
    發表于 12-04 13:49 ?0次下載
    基于<b class='flag-5'>C++11</b>的輕量級對象間通信機制

    了解一下貼片電感的特性特點

    如今在各行各業中,在貼片電感的應用在我們的生活中是非常廣泛的,貼片電感的特點有很多,你對貼片電感的了解有多少呢,貼片電感都有哪些特性呢,今天為大家簡單的介紹一下貼片電感的特點及特性內容。 1、平底
    發表于 06-13 07:39 ?1976次閱讀

    宏碁智能佛珠了解一下

    朋友,最近工作順利嗎?家庭幸福嗎?生活美滿嗎?看你心情復雜,要不要了解一下宏碁剛發布的智能佛珠?
    的頭像 發表于 08-08 16:27 ?3551次閱讀

    《深入理解C++11C++11新特性解析與應用的詳細電子教材免費下載

    國內首本全面深入解讀 C++11 新標準的專著,由 C++ 標準委員會代表和 IBM XL 編譯中國開發團隊共同撰寫。不僅詳細闡述了 C++11 標準的設計原則,而且系統地講解了
    發表于 08-27 08:00 ?0次下載

    初步感知一下C語言

    今天筆者就帶大家跟c語言簡單“相個親”,看看朋友們對c語言的眼緣如何。今天你不需要理解它是什么意思,只是初步感受一下它是什么樣的。
    的頭像 發表于 05-05 20:10 ?1306次閱讀
    初步感知<b class='flag-5'>一下</b><b class='flag-5'>C</b>語言

    std::function簡介及模板類聲明

    包裝類型僅僅依賴于調用特征,而不依賴于可調用元素自身的類型。 std::functionC++11的新特性,包含在頭文件《functional》中。
    的頭像 發表于 07-28 15:30 ?4809次閱讀

    大哥!100W移動電源方案,了解一下

    100W移動電源方案,了解一下
    的頭像 發表于 06-02 19:03 ?2430次閱讀
    大哥!100W移動電源方案,<b class='flag-5'>了解</b><b class='flag-5'>一下</b>

    HONEYWELL霍尼韋爾傳感IC丨磁傳感芯片新品了解一下

    HONEYWELL霍尼韋爾傳感IC丨磁傳感芯片新品了解一下
    的頭像 發表于 06-05 12:41 ?3129次閱讀
    HONEYWELL霍尼韋爾傳感<b class='flag-5'>器</b>IC丨磁傳感<b class='flag-5'>器</b>芯片新品<b class='flag-5'>了解</b><b class='flag-5'>一下</b>?

    C++11新的類功能(特殊成員函數、override和final)

    C++11在原有的4個特殊成員函數(默認構造函數、復制構造函數、復制賦值運算符和析構函數)的基礎上新增了移動構造函數和移動賦值運算符。
    的頭像 發表于 07-18 16:02 ?496次閱讀

    了解一下“薄膜厚度監控”

    光學鍍膜干貨來了!了解一下“薄膜厚度監控”
    的頭像 發表于 07-20 10:11 ?859次閱讀
    <b class='flag-5'>了解</b><b class='flag-5'>一下</b>“薄膜厚度監控”

    如何用C++11實現自旋鎖

    下面我會分析一下自旋鎖,并代碼實現自旋鎖和互斥鎖的性能對比,以及利用C++11實現自旋鎖。 :自旋鎖(spin lock) 自旋鎖是種用于保護多線程共享資源的鎖,與
    的頭像 發表于 11-11 16:48 ?1427次閱讀
    如何用<b class='flag-5'>C++11</b>實現自旋鎖

    基于C++11的線程池實現

    C++11 加入了線程庫,從此告別了標準庫不支持并發的歷史。然而 c++ 對于多線程的支持還是比較低級,稍微高級點的用法都需要自己去實現,譬如線程池、信號量等。 線程池(thread pool
    的頭像 發表于 11-13 15:29 ?759次閱讀
    主站蜘蛛池模板: 狠狠色狠狠色综合日日32| a免费在线观看视频| 中文字幕在线观看亚洲日韩| 最新色导航| jlzz中国jizz日本老师水多| 第一福利在线永久视频| 国产免费内射又粗又爽密桃视频| 国产亚洲精品久久久久久禁果TV | 苍井空教师BD在线观看全集| 丰满五十老女人性视频| 国产无遮挡色视频免费观看性色 | 精品综合久久久久久8888| 久久伊人影院| 欧美手机在线| 午夜理论片日本中文在线| 一本色道久久综合亚洲精品加| 99九九99九九九视频精品| 高h超辣bl文| 精品精品国产yyy5857香蕉| 免费精品一区二区三区AA片| 肉动漫无码无删减在线观看| 亚洲精品一二三| 99精品国产电影| 国产伦精品一区二区三区免费 | 欧美成 人 网 站 免费| 天上人间影院久久国产| 诱人的秘书BD在线观看| 超级最爽的乱淫片免费| 精品国产福利一区二区在线| 欧美日韩免费看| 亚洲精品久久久992KVTV| 99精品视频在线观看免费| 国产热久久精| 牛牛在线精品视频(正)| 小箩莉奶水四溅小说| 99精品免费久久久久久久久日本 | 在线观看免费av网站| 宝贝你骚死哥了好爽| 激情内射亚洲一区二区三区爱妻| 欧美夜夜噜2017最新| 亚洲三级视频|