C 11 Lambda表示式和bind

2021-10-02 03:46:10 字數 3548 閱讀 3217

對於stl中的演算法,我們都可以傳遞任何類別的可呼叫物件。對於乙個物件或乙個表示式,如果可以對其使用呼叫運算子,則稱它為可呼叫的。即,如果e是乙個可呼叫的表示式,則我們可以編寫**e(args),其中args是乙個逗號分隔的乙個或多個引數的列表。

一般來說,有四種可呼叫物件:函式,函式指標,過載了函式呼叫運算子的類,以及lambda表示式。

1. 概述

乙個lambda表示式表示乙個可呼叫的**單元。我們可以將其理解為乙個未命名的內聯函式。與任何函式類似,乙個lambda具有乙個返回型別、乙個引數列表和乙個函式體。但與函式不同,lambda可能定義在函式內部。

乙個lambda的通用表示式為:

[capture list] (parameter list) -> return type
舉個簡單的例子:

auto f =  ;

cout << f() << endl; //列印42

注意,忽略括號和引數列表相當於指定了空的引數列表。如果函式體為一條return語句,lambda將根據**推斷返回型別,否則型別為void。

2. 傳遞引數

如函式一樣,lambda表示式也可以傳遞引數,但是不同的是,其不能有預設引數。乙個lambda呼叫的實參數目永遠要和形引數目相等。

舉個例子:

auto f = (const string &lhs, const string &rhs) 

;

3. 使用捕獲列表

所謂捕獲列表,則是中括號中的引數,表示使用其所在函式中的任何區域性變數。捕獲的方式有三種:值捕獲引用捕獲隱式捕獲

1、空,沒有使用任何函式物件引數。

2、=,函式體內可以使用lambda所在作用範圍內所有可見的區域性變數(包括lambda所在類的this),並且是值傳遞方式(相當於編譯器自動為我們按值傳遞了所有區域性變數)。

3、&,函式體內可以使用lambda所在作用範圍內所有可見的區域性變數(包括lambda所在類的this),並且是引用傳遞方式(相當於編譯器自動為我們按引用傳遞了所有區域性變數),不過要注意是const引用。

size_t v1 = 42;

auto f = [&]() ;

// v1 = 0;

auto j = f();

cout << "end:" << j << endl;

cout << v1 << endl;

捕捉列表按引用傳遞可以修改傳遞物件的值,v1的值成了1000

4、this,函式體內可以使用lambda所在類中的成員變數。同理this的含義,按*this傳遞,可修改類成員age的值,變成了10000

5、a,將a按值進行傳遞。按值進行傳遞時,函式體內不能修改傳遞進來的a的拷貝,因為預設情況下函式是const的。要修改傳遞進來的a的拷貝,可以新增mutable修飾符。

6、&a,將a按引用進行傳遞。

7、a, &b,將a按值進行傳遞,b按引用進行傳遞。

8、=,&a, &b,除a和b按引用進行傳遞外,其他引數都按值進行傳遞。

9、&, a, b,除a和b按值進行傳遞外,其他引數都按引用進行傳遞。

如前面所提到,如果乙個lambda體包含return之外的任何語句,則編譯器假定此lambda返回void。

//錯誤示範:編譯器推斷為void,實際為int

auto f = (int i) ;

//可以修改為如下

auto f = (int i) -> int ;

1.可將bind函式看作是乙個通用的函式介面卡,它接受乙個可呼叫物件,生成乙個新的可呼叫物件來「適應」原物件的引數列表。

呼叫bind的一般形式為:

auto newcallable = bind(callable,arg_list);
2.arg_list中的引數可能包含形如_n的名字,其中n是乙個整數,這些引數是「佔位符」,表示newcallable的引數,它們佔據了傳遞給newcallable的引數的「位置」。數值n表示生成的可呼叫物件中引數的位置:_1為newcallable的第乙個引數,_2為第二個引數,以此類推

佔位符型別作用域

using namespace std::placeholders;
例子:

int f(int a, int b, int c) 

//呼叫處

auto g = bind(f, _2, _1, 11);//注意:此處引數順序.._2,_1),但是bind函式引數順序是(20,10)

int k = g(10, 20);

cout << k << endl; //輸出21

實際應用中:

bool check_size(const int x, int sz) 

//呼叫處

int n = 5;

//有bind函式新封裝生成的函式,其內部呼叫了check_size

auto new_check_size = bind(check_size, std::placeholders::_1, n);

auto it = find_if(v.begin(), v.end(), new_check_size);

cout << "第乙個大於n的數為:" << *it << endl;

例如cocos中也是類似實現方式:

進入cc_callback_1實現:

為了與不支援拷貝的引數繫結,bind經常和ref一起用,ref也定義在標頭檔案functional中,作用是返回乙個引用物件。

ostream &print(ostream &os, const string &s, char c) 

//錯誤示範

for_each(words.begin(), words.end(), bind(print, os, _1, ' '));

//正確示範

for_each(words.begin(), words.end(), bind(print, ref(os), _1, ' '));

C 11 lambda表示式 詳解

如下圖,lambda表示式由下面幾個部分構成 c 11 的 lambda 表示式規範如下 mutable 修飾符說明 lambda 表示式體內的 可以修改 獲的變數,並且可以訪問 獲物件的 non const 方法。exception 說明 lambda 表示式是否丟擲異常 noexcept 以及丟...

C 11 lambda 表示式解析

中括號中 from 下面是各種變數擷取的選項 小括號中,就是函式引數 lambda表示式可以作為其它函式引數 1 標準格式 有箭頭 就要顯示寫明返回值型別 auto pfunc1 this void pfunc1 2 簡化格式 void 型別返回值 沒有箭頭 會預設檢測返回值型別 auto pfun...

C 11 Lambda表示式簡介

lambda簡介 capture列表 mutable說明 c 11中的lambda 表示式用於定義並建立匿名的函式物件,以簡化程式設計工作。lambda表示式一般都是從方括號開始,然後結束於花括號 主要包括五個部分 常見幾種lambda表示式形式 表示式 capture params mutable...