日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 單片機(jī) > 程序喵大人

你有沒(méi)有遇到過(guò)這種場(chǎng)景?

寫(xiě)回調(diào)函數(shù)時(shí),糾結(jié)到底該用“函數(shù)指針”還是“l(fā)ambda”?又或者,看到 C++ STL 里頻繁出現(xiàn)的“函數(shù)對(duì)象(仿函數(shù))”,忍不住一臉懵圈:這仨玩意兒,真的有那么多區(qū)別嗎?

今天,我們就來(lái)一口氣講清楚這三個(gè)在 C++ 中常見(jiàn)的“可調(diào)用對(duì)象”,不僅要分清它們的語(yǔ)法差異,更要搞懂 它們背后的性能差異實(shí)際應(yīng)用建議。

一、三個(gè)概念先講清

? 函數(shù)指針(Function Pointer)

最傳統(tǒng)的調(diào)用方式,C語(yǔ)言遺產(chǎn)。

void say_hello() {  std::cout << "Hello!\n"; }  void call(void (*func)()) {  func(); // 函數(shù)指針調(diào)用 } 

適合傳遞普通函數(shù),語(yǔ)法較繁瑣,對(duì)類型要求嚴(yán)格,不支持捕獲外部變量。

? 函數(shù)對(duì)象 / 仿函數(shù)(Function Object)

本質(zhì)是一個(gè)“重載了 operator() 的類”,可以像函數(shù)一樣使用對(duì)象。

struct Adder {  int operator()(int a, int b) const {  return a + b;  } }; 

優(yōu)點(diǎn)是可攜帶狀態(tài)、可內(nèi)聯(lián)優(yōu)化,STL 算法中大量使用,比如 std::sort 搭配比較器。

? Lambda 表達(dá)式

C++11 后的香餑餑,本質(zhì)是一個(gè)匿名的函數(shù)對(duì)象,寫(xiě)法靈活、可捕獲變量。

auto adder = [](int a, int b) { return a + b; }; 

既能像函數(shù)指針那樣使用,又能像函數(shù)對(duì)象一樣攜帶狀態(tài),兼具兩者優(yōu)點(diǎn)。

二、核心問(wèn)題:哪個(gè)性能更高?

結(jié)論先行:

函數(shù)對(duì)象 ≈ lambda > 函數(shù)指針 > std::function

是不是有點(diǎn)出乎意料?我們一個(gè)個(gè)講。

1. 函數(shù)對(duì)象 vs lambda:幾乎打平

因?yàn)?lambda 本質(zhì)就是編譯器幫你生成的匿名函數(shù)對(duì)象,它們都是 編譯期類型、可以被 內(nèi)聯(lián)優(yōu)化。

舉個(gè)例子:

#include  #include   std::vector<int> vec = {3, 1, 4, 1, 5};  std::sort(vec.begin(), vec.end(), [](int a, int b) {  return a > b; }); 

這個(gè) lambda 表達(dá)式,最終會(huì)被編譯器轉(zhuǎn)成類似如下結(jié)構(gòu):

struct Comp {  bool operator()(int a, int b) const { return a > b; } }; 

也就是說(shuō),從性能角度來(lái)看,lambda 和你手寫(xiě)的函數(shù)對(duì)象效果是一樣的,區(qū)別只是有沒(méi)有名字而已。

優(yōu)勢(shì):可內(nèi)聯(lián)優(yōu)化、零額外開(kāi)銷劣勢(shì):略顯抽象,捕獲變量時(shí)可能造成誤用(比如引用捕獲生命周期問(wèn)題)

2. 函數(shù)指針:靈活但“冷門(mén)”

函數(shù)指針因?yàn)槭?運(yùn)行時(shí)確定的函數(shù)地址,所以不能內(nèi)聯(lián),性能略差。

void foo() { std::cout << "Hello\n"; } void run(void (*fp)()) { fp(); } 

相比函數(shù)對(duì)象或 lambda,它的開(kāi)銷略高,主要體現(xiàn)在:

  • 無(wú)法內(nèi)聯(lián) → 函數(shù)調(diào)用成本更高
  • 不能攜帶狀態(tài) → 擴(kuò)展性差
  • 類型不靈活 → 泛型編程不友好

但它依然有用武之地,比如你要調(diào)用某個(gè)庫(kù)函數(shù)的鉤子、處理 C 風(fēng)格 API(如 qsort)時(shí),函數(shù)指針是必須的。

3. std::function:最靈活也最慢

std::function 是一個(gè) 類型擦除容器,可以包裝任意可調(diào)用對(duì)象(包括函數(shù)指針、lambda、仿函數(shù)等),代價(jià)是:

  • 要在堆上分配空間(如果可調(diào)用對(duì)象太大)
  • 無(wú)法內(nèi)聯(lián)
  • 性能開(kāi)銷比前三者都大
std::function<void()> func = [] { std::cout << "Hello\n"; }; 

建議在 必須多態(tài)傳參統(tǒng)一接口 場(chǎng)景下使用,其他場(chǎng)景謹(jǐn)慎上。

三、實(shí)際開(kāi)發(fā)怎么選?

場(chǎng)景 推薦使用 原因
STL 算法排序、查找等 lambda / 仿函數(shù) 編譯期優(yōu)化,零開(kāi)銷
回調(diào)函數(shù) / 鉤子傳參 函數(shù)指針 簡(jiǎn)潔直觀
狀態(tài)攜帶、靈活封裝 lambda / 仿函數(shù) 可維護(hù)性強(qiáng)
多態(tài)可調(diào)用對(duì)象封裝 std::function 提高通用性,犧牲性能

總結(jié):不要為了“酷”而用 lambda

雖然 lambda 是現(xiàn)代 C++ 的明星,但它并非萬(wàn)能:

  • 如果你只需要傳個(gè)裸函數(shù)地址,用函數(shù)指針更輕量;
  • 如果你需要封裝復(fù)雜邏輯,lambda、仿函數(shù)才是首選;
  • 如果你想要靈活接口、動(dòng)態(tài)傳參,那就老老實(shí)實(shí)用 std::function 吧。

?最重要的是:理解每種可調(diào)用對(duì)象的代價(jià)和場(chǎng)景,才是“高效”的真諦。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉