c c 補完計畫 六 語法糖lambda

2021-10-11 18:49:20 字數 3847 閱讀 3682

function

bind

最後

很多語言都有lambda, c++自然不能缺, 在c++11裡面加入了, 是程式猿喜歡的語法糖, 便於閱讀, 也便於理解. 當然, 它有很多相關概念, 這裡盡可能展開說.

[capture list] (params list) mutable exception-> return type
你會覺得和函式宣告很像, 但是注意,不可以有預設值,也不支援可變引數, 類似printf,引數必須要有引數名. 甚至你會覺得和python3很像, 尤其是這個->return type, 所以你看, c++也越來越友好了.

先來幾個小栗子:

auto f = (int a, int b) ;

cout << f(1, 5) << endl;

可以看到a, b是形參, 1, 5是實參, f似乎是函式, 這個放到後面說.

int x = 3, y = 5;

auto f2 = [x, y] ;

cout << f2() << endl;

然後你發現, lambda更神奇的地方在於, 可以捕獲外界引數, 是不是很酷, 其實這裡本質還是值傳遞, 當然後面有引用, 但是預設是值傳遞.

捕獲形式說明

不捕獲任何外部變數

[var1,var2, …]

預設以值得形式捕獲指定的多個外部變數(用逗號分隔)

[this]

以值的形式捕獲this指標

[=]以值的形式捕獲所有外部變數

[&]以引用形式捕獲所有外部變數

[=, &var1]

變數var1以引用形式捕獲,其餘變數以傳值形式捕獲

[&, var1]

變數var1以值的形式捕獲,其餘變數以引用形式捕獲

很多都是一眼懂, 舉個栗子吧:

int x = 1, y = 2, z = 3;

cout << "before: " << x << ' ' << y << ' ' << z << endl;

auto f = [&, x]()mutable ;

f();

cout << "after: " << x << ' ' << y << ' ' << z << endl;

before: 1 2 3

in: 5 6 7

after: 1 6 7

x是值傳遞, y, z是引用傳遞, 值傳遞實際上是不能修改的, 但是這裡加了mutable, 所以可以在函式體內進行改動. 然後引用傳入, 會對外部產生影響, 值傳入則不會, 很好理解.

甚至可以傳入this指標.

class a 

void foo(vector&v) );

}private:

int data;

};vectorv;

a a(3);

a.foo(v);

before: 1

after: 4

before: 2

after: 5

before: 3

after: 6

傳入this指標之後, 就可以使用成員變數.

然後你會發現乙個問題, 我這裡寫的都是auto, 那具體是什麼呢?

functionf = (int a, int b) ;
返回一開始的栗子, 看到function裡面寫了函式的返回值, 然後括號裡面是引數型別.

std::function是乙個可呼叫物件包裝器,是乙個類模板,可以容納除了類成員函式指標之外的所有可呼叫物件,它可以用統一的方式處理函式、函式物件、函式指標,並允許儲存和延遲它們的執行。

目的肯定是取代函式指標的, 來看乙個栗子:

functionadd = (int a, int b) ;

cout << add(1, 5) << endl;

functiondiv = (int a, int b) ;

cout << div(5, 1) << endl;

想想之前的寫法, 是不是用巨集定義乙個函式指標, 類似typedef int(*fp)(int, int);, 是不是很像, 用function的話, 整體也更直觀好操作.

曾經我被問到, 如何實現lambda獲取外部引數的功能, 那答案就是利用bind, 先來看個栗子:

functiondiv = (int a, int b) ;

cout << div(5, 1) << endl;

auto divex = bind(div, placeholders::_2, placeholders::_1);

cout << divex(5, 1) << endl;

5

0

是不是挺酷的, 什麼都沒改, 就把引數位置換了.

a a;

auto ret = bind(&a::f, &a, 5, placeholders::_1);

cout << ret(3) << endl;

之前也說了, lambda是不支援預設引數的, 但是通過bind+佔位符, 就很好實現了這個點, 甚至可以隨意調整引數位置. 而且可以繫結成員函式, 不過你需要傳入具體例項在第二個引數.

void print(ostream &os, string &str, char space)

ostringstream os;

vectordata;

char space = ' ';

for_each(data.begin(), data.end(), bind(print, ref(os), placeholders::_1, space));

cout << os.str() << endl;

os.str("");

for_each(data.begin(), data.end(), [&os, space](string &str));

cout << os.str() << endl;

os.str("");

auto printl=[&os, space](string&str){os《最後對比下bind和lambda, 當然二者是可以配合使用的, 怎麼用還是看自己. 我的話, 怎麼簡潔怎麼用.

ref簡單說下, 主要是有些變數不支援值傳遞, bind這裡就要寫成ref(os).

真的是很實用的點, 讓c++靈活了很多. 就像設計了while之後, 又設計了for, 設計了for之後又設計了for_each, 語言都是不斷發展的, 學習新的真的很有必要.

c c 補完計畫 三 素數統計

統計所有小於非負整數 n 的質數的數量 這是一道leetcode簡單級別的,本來沒啥說的,然後我發現了尤拉篩選法.常規思路就是對每個數x進行檢測,用x除以2到根號x,有乙個可以整除,就不是素數.優點是連陣列或者vector都不需要,有乙個算乙個,很節省空間.bool isprime int i re...

OC第六講 Block,語法糖

一 main.m import import student.h 函式宣告 int maxvalue int a,int b 函式定義 int maxvalue int a,int b 函式指標型別 int int,int 函式指標變數 int aaa int,int null 重新命名資料型別 t...

c c 補完計畫 一 指標常量和常量指標

想寫點c c 的東西.乙個題,要寫出以下4種情況的輸出 int main 說實話,算是送分題,基本上你看過一遍也就會了,但是沒看過,你可能就暈了.常量指標意味著字串內容不可變,如果嘗試修改,在寫出賦值 的時候,ide就會告訴你這是錯誤的,好理解.指標常量意味著指向位址是不變的,內容可變.嘗試賦值,i...