24C 複習 Lamda表示式 可變引數模板

2022-10-08 20:12:19 字數 4286 閱讀 7838

lamda表示式是c++11中引入的一項新技術,利用lamda表示式可以編寫內嵌的匿名函式,用以替換獨立函式或者函式物件,並且使得**更可讀。是一種匿名函式,即沒有函式名的函式;lamda函式的語法定義如下:

[capture] :捕捉列表,捕捉列表總是作為lambda的開始,即出現於lambda的開始處。它是lambda的引出符(即開始標誌)。編譯器可以根據該「標誌」來作出判斷出該函式是否為lambda函式。同時「捕捉列表」能夠捕捉上下文中的變數以作為lambda函式使用。

(parameters):引數列表。和c/c++中的普通函式引數意義一樣。該部分是可選的,意味著如果我們不需要進行引數傳遞時,可以連同括號「()」一起省略掉。

mutable:該關鍵字為乙個修飾符。在預設的情況下,lambda函式總是返回乙個const,而當我們在引數列表後面註明了「mutable」關鍵字之後,則可以取消其常量性質。若在lambda中使用了mutable修飾符,則「引數列表」是不可省略掉的(即使是引數為空)。

->return-type: 函式的返回值型別。和c/c++中的普通函式返回值型別的性質一樣。主要目的是用來追蹤lambda函式(有返回值情況下)的返回型別。若lambda函式不需要返回值,則可以直接將這部分省略掉。

:函式體。在該函式體中,除了可以使用引數列表中的變數外,還可以使用所有捕獲到的變數(即[capture] 中的變數)。

【示例】

// 指明返回型別

auto add = (int a, int b) -> int ;

// 自動推斷返回型別

auto multiply = (int a, int b) ;

int sum = add(2, 5); // 輸出:7

int product = multiply(2, 5); // 輸出:10

c++11中的lambda函式,其中的「捕捉列表」是由0個或多個「捕捉項」組成,並以逗號「,」分隔。捕捉列表有如下幾種形式:

(1)預設不捕獲任何變數;

(2)[var]表示值傳遞方式捕捉變數var;

(3)[=]表示值傳遞方式捕捉所有***域的變數(包括this);

(4)[&var]表示引用傳遞捕捉所有變數var;

(5)[&] 表示引用傳遞捕捉所有父作用域的比**(包括this);

(6)[=, &x]表示以值捕獲所有變數,當x例外,通過引用捕獲;

(7)[&, x]表示以引用捕獲所有變數,但x例外,通過值捕獲;

(8)[this] 表示引用捕獲當前物件(其實是複製指標);

(9)[*this]表示通過值方式捕獲當前物件;

【示例1】

#include #include #include using namespace std; 

int main()

; printf("sum[%d]\n",retval());

printf("a[%d] b[%d] c[%d]\n",a,b,c);

return 0;

}

執行結果:

inner c[3]

inner c2[30]

sum[30]

a[10] b[20] c[3]

【示例2】

#include #include #include using namespace std; 

int main()

; printf("sum[%d]\n",retval());

printf("a[%d] b[%d] c[%d]\n",a,b,c);

return 0;

}

執行結果:

inner a[1] b[2] c[3]

sum[30]

a[10] b[20] c[30]

關於c++11中lamda表示式更詳盡的內容參見:

在c++11之前,類模板和函式模板只能含有固定數量的模板引數。c++11增強了模板功能,允許模板定義中包含0到任意個模板引數,這就是可變引數模板。

可變引數模板和普通模板的語義是一樣的,只是寫法上稍有區別,宣告可變引數模板時需要在typename或class後面帶上省略號「…」:

templatevoid func(t ... args)//t叫模板引數包,args叫函式引數包 

func(); // ok:args不含有任何實參

func(1); // ok:args含有乙個實參:int

func(2, 1.0); // ok:args含有兩個實參int和double

定義乙個可變引數模板函式的定義如下:

#include using namespace std; 

templatevoid func(t ... args)

int main()

執行結果:

num = 0

num = 1

num = 2

引數包的展開(1)遞迴方式展開

通過遞迴函式展開引數包,需要提供乙個引數包展開的函式和乙個遞迴終止函式。

#include using namespace std; 

//遞迴終止函式

void debug()

//展開函式

template void debug(t first, args ... last)

int main()

執行結果:

parameter 1

parameter 2

parameter 3

parameter 4

empty

(2)非遞迴方式展開

#include using namespace std; 

template void print(t arg)

template void expand(args ... args)

; }

int main()

執行結果:

123

4

【示例】通過可變引數模板實現列印函式

#include #include using namespace std; 

void debug(const char* s)

cout << *s++;

} } templatevoid debug(const char* s, t value, args... args)

cout << *s++;

} throw runtime_error("extra arguments provided to debug");

} int main()

執行結果:

(1)繼承方式展開引數包

可變引數模板類的展開一般需要定義2 ~ 3個類,包含類宣告和特化的模板類:

#include #include using namespace std; 

templateclass bmw{}; // 變長模板的宣告

template// 遞迴的偏特化定義

class bmw: public bmw

head head;

}; template<> class bmw<>{}; // 邊界條件

int main()

執行結果:

type:f

type:c

tepy:i

(2)模板遞迴和特化方式展開引數包

#include using namespace std; 

template struct multiply;// 變長模板的宣告

template struct multiply// 變長模板類

; template<> struct multiply<> // 邊界條件

; int main()

執行結果:

120

C 委託 Lamda表示式

1 using system 2using system.collections.generic 3using system.linq 4using system.text 5using system.threading.tasks 67 namespace816 17static void mai...

C 中委託,匿名函式,lamda表示式複習

一 委託 1.就給模擬較,類用class宣告,委託用delegate宣告。2.委託要指向乙個真正的方法。3.委託的簽名,要和指向的方法一樣。1.宣告乙個委託 public delegate void delsayhi string name public static void sayhichine...

LAMDA表示式學習

1.普通繫結 public void button1 click object sender,eventargs e this.button1.click button1 click 2.匿名委託 this.button1.click delegate object sender,eventargs...