https://www.cnblogs.com/bencai/p/9124654.html //關于function
https://www.cnblogs.com/geloutingyu/p/8335230.html //關于lambda、bind
泛型程式設計思想
- 序
- 函數指針
- function
- lambda
序
為編寫更通用的代碼,将資料類型與方法、類分離,這就是泛型程式設計思想。
C++ 的三大面向對象特性:封裝、繼承、多态。它們分别保證了安全性、可複用性以及特性。
偷懶是人類的重要生産力。
從類的繼承、template、函數指針,再到function、lambda,均是為了踐行泛型程式設計思想,讓偷懶更成功。
下面給出幾個常用、淺顯、直覺的例子,學習函數指針、function、lambda的使用。
函數指針
#include<iostream>
using namespace std;
class Foo
{
public:
void foo(int i) { cout << "Foo:" << i << endl; }
};
void foo(int i) { cout << i << endl;}
int main()
{
void (*func1) (int x);
func1 = foo;
func1(1);
void (Foo::*func2) (int);
func2 = Foo::foo;
Foo f;
(f.*func2)(2);//一個很别扭但正确的調用方式,成員函數必須綁定到一個對象執行個體上
}
main函數裡的第一部分是普通函數的函數指針的使用。第二部分是類成員函數的函數指針的使用。
function
https://www.cnblogs.com/bencai/p/9124654.html
lambda
lambda是一種一次性的匿名函數,有定義而無函數名,與普通函數性能一樣強。
形式為:
[捕獲清單](參數清單) ->傳回值{函數體}
主要說說
捕獲清單
:
1、預設情況下,即捕獲字段為 [] 時,lambda表達式是不能通路任何外部變量的,即表達式的函數體内無法通路目前作用域下的變量。
2、
=
函數體内可以使用 Lambda 所在範圍内所有可見的局部變量(包括 Lambda 所在類的 this),并且是值傳遞方式(相當于編譯器自動為我們按值傳遞了所有局部變量)。
3、
&
函數體内可以使用 Lambda 所在範圍内所有可見的局部變量(包括 Lambda 所在類的 this),并且是引用傳遞方式(相當于是編譯器自動為我們按引用傳遞了所有局部變量)。
4、
this
函數體内可以使用 Lambda 所在類中的成員變量。
5、
a
将 a 按值進行傳遞。按值進行傳遞時,函數體内不能修改傳遞進來的 a 的拷貝,因為預設情況下函數是 const 的,要修改傳遞進來的拷貝,可以添加 mutable 修飾符。
6、
&a
将 a 按引用進行傳遞。
7、
a,&b
将 a 按值傳遞,b 按引用進行傳遞。
8、
=,&a,&b
除 a 和 b 按引用進行傳遞外,其他參數都按值進行傳遞。
9、
&,a,b
除 a 和 b 按值進行傳遞外,其他參數都按引用進行傳遞。
下面是一個簡單的捕獲局部變量的例子,學習一下捕獲清單裡的&:
//exp1:
int test = 1;
int a = 2;
int b = 3;
auto func1 = [&](int a, int b) {
++a;
++b;
++test;
return test + a + b;
};
cout << "default capture list, result = " << func1(a, b) << endl;
cout << "test = " << test << " , a = " << a << " , b = " << b << endl;
這裡capture list裡的&符号指的是lambda外部的局部變量按照引用傳值,
這裡的引用不針對參數清單裡的a和b
——換言之,參數清單裡的參數如何傳參,與捕獲清單裡的局部變量如何傳參,是兩回事。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL0YTNzMTN1ATM4ATNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
可以看到,a和b的值仍然是2和3,test的值從1變為2。
下面是一個簡單的捕獲局部變量的例子,學習一下捕獲清單裡的=:
int test = 1;
int a = 2;
int b = 3;
auto func2 = [=](int a, int b) mutable{
++a;
++b;
++test;
return a + b;
};
cout << "default capture list, result = " << func2(a, b) << endl;
cout << "test = " << test << " , a = " << a << " , b = " << b << endl;
這裡必須加mutable 正如本節5所說,如果是傳值且想改變該值,必須用mutable修飾。如果不加,會出現以下錯誤:
是以筆者猜測,傳值後,編譯器将該值加了const修飾。
關于捕獲的更多細節、傳回值、bind、lambda的常見應用,可以參考第二條引用連結。在此感謝作者的分享~
目前正在開發的jojo_webserver裡也使用了function、lambda以及bind,過段時間寫好部落格發上來。