C++11中的一些泛型編程思想——函數指針、function、lambda

https://www.cnblogs.com/bencai/p/9124654.html //關於function
https://www.cnblogs.com/geloutingyu/p/8335230.html //關於lambda、bind

爲編寫更通用的代碼,將數據類型與方法、類分離,這就是泛型編程思想。

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——換言之,參數列表裏的參數如何傳參,與捕獲列表裏的局部變量如何傳參,是兩回事。
在這裏插入圖片描述
可以看到,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,過段時間寫好博客發上來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章