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...