一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

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

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

重點(diǎn)了解一下C++11 包裝器function

冬至子 ? 來(lái)源:iDoitnow ? 作者:艱默 ? 2023-07-18 16:41 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

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

對(duì)于function, C++ 參考手冊(cè)給出的定義為:

類(lèi)模板 std::function 是通用多態(tài)函數(shù)封裝器。std::function 的實(shí)例能存儲(chǔ)、復(fù)制及調(diào)用任何可調(diào)用 (Callable) 目標(biāo)——函數(shù)、 lambda 表達(dá)式、 bind 表達(dá)式或其他函數(shù)對(duì)象,還有指向成員函數(shù)指針和指向數(shù)據(jù)成員指針。

C++11為什么要引入function

我們先看一個(gè)例子:

#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是函數(shù)名(函數(shù)名是一個(gè)指針),
    因此參數(shù)F對(duì)應(yīng)的類(lèi)型為double(*)double,
    即一個(gè)指向(接受一個(gè)double參數(shù)并返回一個(gè)double的)函數(shù)指針*/
    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)是一個(gè)參數(shù)對(duì)象,F(xiàn)對(duì)應(yīng)的類(lèi)型為Fp
    cout < < " " < < use_f(y, Fp(5.0)) < < endl;
    cout < < "Function object Fq:n";
    //Fq(5.0)是一個(gè)參數(shù)對(duì)象,F(xiàn)對(duì)應(yīng)的類(lèi)型為Fq
    cout < < " " < < use_f(y, Fq(5.0)) < < endl;
    
    cout < < "Lambda expression 1:n";
    //此處是一個(gè)lambda表達(dá)式,F(xiàn)對(duì)應(yīng)的類(lèi)型為該lambda表達(dá)式使用的類(lèi)型
    cout < < " " < < use_f(y, [](double u) { return u * u; }) < < endl;
    cout < < "Lambda expression 2:n";
    ////此處是一個(gè)lambda表達(dá)式,F(xiàn)對(duì)應(yīng)的類(lèi)型為該lambda表達(dá)式使用的類(lèi)型
    cout < < " " < < use_f(y, [](double u) { return u + u / 2.0; }) < < endl;
    return 0;
}

程序通過(guò)一個(gè)模板函數(shù)use_f使用參數(shù)f表示調(diào)用的類(lèi)型,然后將f(v)返回。在主函數(shù)中我們6次調(diào)用模板函數(shù),對(duì)于前兩個(gè)調(diào)用的use_f為同一個(gè)實(shí)例化。后面四個(gè),每一個(gè)都有其對(duì)應(yīng)use_f的實(shí)例化。實(shí)際上,上述代碼的運(yùn)行結(jié)果如下:

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

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

針對(duì)例子中的函數(shù)指針、函數(shù)對(duì)象和lambda表達(dá)式,它們有一個(gè)共同的特征:都是接受一個(gè)double參數(shù)并返回一個(gè)double值。也就是它們的調(diào)用特征標(biāo)(它們的特征標(biāo)都是double(double))相同。這便是function解決這個(gè)問(wèn)題的關(guān)鍵?!? :調(diào)用特征標(biāo)是由返回類(lèi)型和參數(shù)類(lèi)型列表決定的,其格式為:返回類(lèi)型(參數(shù)類(lèi)型列表),其中每個(gè)參數(shù)類(lèi)型用逗號(hào)分隔?!?/p>

因此,C++11引入了function包裝器。function包裝器可以簡(jiǎn)單理解為一個(gè)接口,它可以將特征標(biāo)相同的函數(shù)指針、函數(shù)對(duì)象和lambda表達(dá)式等統(tǒng)一定義為一類(lèi)特殊的對(duì)象。

function的用法

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

template< class >
class function; 

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

其中R為被調(diào)用函數(shù)的返回類(lèi)型,Args為被調(diào)用函數(shù)的形參。存儲(chǔ)的可調(diào)用對(duì)象被稱(chēng)為std::function的目標(biāo),如果目標(biāo)為空,則調(diào)用空的function會(huì)導(dǎo)致拋出std::bad_function_call異常。

示例:

#include < functional >
#include < iostream >

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

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

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

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

輸出結(jié)果為:

-9
4
bad_function_call

在了解完function的用法之后,回到我們最開(kāi)始的問(wèn)題,其中,6次循環(huán)中要處理的目標(biāo)的特征標(biāo)均為double(double),因此,我們班使用function包裝器將它們將統(tǒng)一“包裝”成function類(lèi)型,這樣模板函數(shù)use_f將只實(shí)例化一次。使用function包裝器改進(jìn)后的代碼如下所示:

#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;
}

輸出結(jié)果為:

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

從輸出結(jié)果可以看出,use_f確實(shí)只實(shí)例化了一次,增加了編碼效率,6次循環(huán)調(diào)用同一個(gè)函數(shù),增加了代碼額執(zhí)行效率。

總結(jié)

function包裝器將可調(diào)用對(duì)象的類(lèi)型進(jìn)行統(tǒng)一,便于我們對(duì)其進(jìn)行統(tǒng)一化管理,同時(shí),使用function包裝器可以解決模板效率低下,實(shí)例化多份的問(wèn)題。

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

    關(guān)注

    38

    文章

    7649

    瀏覽量

    167315
  • C++語(yǔ)言
    +關(guān)注

    關(guān)注

    0

    文章

    147

    瀏覽量

    7295
  • 封裝器
    +關(guān)注

    關(guān)注

    0

    文章

    7

    瀏覽量

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

掃碼添加小助手

加入工程師交流群

    評(píng)論

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

    使用C++11新特性實(shí)現(xiàn)個(gè)通用的線(xiàn)程池設(shè)計(jì)

    C++11標(biāo)準(zhǔn)之前,多線(xiàn)程編程只能使用pthread_xxx開(kāi)頭的組POSIX標(biāo)準(zhǔn)的接口。從C++11標(biāo)準(zhǔn)開(kāi)始,多線(xiàn)程相關(guān)接口封裝在了C++的std命名空間里。
    的頭像 發(fā)表于 12-22 13:58 ?1980次閱讀
    使用<b class='flag-5'>C++11</b>新特性實(shí)現(xiàn)<b class='flag-5'>一</b>個(gè)通用的線(xiàn)程池設(shè)計(jì)

    C++標(biāo)準(zhǔn)庫(kù)學(xué)習(xí)筆記重點(diǎn)

    新特性:1.C++98源碼編譯后二進(jìn)制文件不能被C++11調(diào)用兼容,須在C++11重新編譯源碼。2.“在兩個(gè)template表達(dá)式的閉符之間放
    發(fā)表于 10-23 20:28

    如何在rt-thread的env環(huán)境中配置C++11?

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

    基于C++11的輕量級(jí)對(duì)象間通信機(jī)制

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

    了解一下貼片電感的特性特點(diǎn)

    如今在各行各業(yè)中,在貼片電感的應(yīng)用在我們的生活中是非常廣泛的,貼片電感的特點(diǎn)有很多,你對(duì)貼片電感的了解有多少呢,貼片電感都有哪些特性呢,今天為大家簡(jiǎn)單的介紹一下貼片電感的特點(diǎn)及特性?xún)?nèi)容。 1、平底
    發(fā)表于 06-13 07:39 ?2120次閱讀

    宏碁智能佛珠了解一下

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

    《深入理解C++11C++11新特性解析與應(yīng)用的詳細(xì)電子教材免費(fèi)下載

    國(guó)內(nèi)首本全面深入解讀 C++11 新標(biāo)準(zhǔn)的專(zhuān)著,由 C++ 標(biāo)準(zhǔn)委員會(huì)代表和 IBM XL 編譯中國(guó)開(kāi)發(fā)團(tuán)隊(duì)共同撰寫(xiě)。不僅詳細(xì)闡述了 C++11 標(biāo)準(zhǔn)的設(shè)計(jì)原則,而且系統(tǒng)地講解了
    發(fā)表于 08-27 08:00 ?0次下載

    初步感知一下C語(yǔ)言

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

    std::function簡(jiǎn)介及模板類(lèi)聲明

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

    大哥!100W移動(dòng)電源方案,了解一下

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

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

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

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

    C++11在原有的4個(gè)特殊成員函數(shù)(默認(rèn)構(gòu)造函數(shù)、復(fù)制構(gòu)造函數(shù)、復(fù)制賦值運(yùn)算符和析構(gòu)函數(shù))的基礎(chǔ)上新增了移動(dòng)構(gòu)造函數(shù)和移動(dòng)賦值運(yùn)算符。
    的頭像 發(fā)表于 07-18 16:02 ?721次閱讀

    了解一下“薄膜厚度監(jiān)控”

    光學(xué)鍍膜干貨來(lái)了!了解一下“薄膜厚度監(jiān)控”
    的頭像 發(fā)表于 07-20 10:11 ?1111次閱讀
    <b class='flag-5'>了解</b><b class='flag-5'>一下</b>“薄膜厚度監(jiān)控”

    如何用C++11實(shí)現(xiàn)自旋鎖

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

    基于C++11的線(xiàn)程池實(shí)現(xiàn)

    C++11 加入了線(xiàn)程庫(kù),從此告別了標(biāo)準(zhǔn)庫(kù)不支持并發(fā)的歷史。然而 c++ 對(duì)于多線(xiàn)程的支持還是比較低級(jí),稍微高級(jí)點(diǎn)的用法都需要自己去實(shí)現(xiàn),譬如線(xiàn)程池、信號(hào)量等。 線(xiàn)程池(thread pool
    的頭像 發(fā)表于 11-13 15:29 ?1023次閱讀