匿名函數lambda表達式

匿名函數lambda表達式


在C++11中引入了匿名函數,也就是所謂的lambda表達式;其實這個表達式在python、JAVA等語言中早就已經存在了,但是很不建議大家使用這個表達式;原因是這種表達式一出現,很多人都是蒙圈的,但是偏偏有很大一部分人喜歡使用,簡便;程序員的世界是不懂的,只能隨他們去吧!!!

但是,作爲一名程序員,自己不寫這類惹人蒙圈的東西,但是要能看的懂這類騷操作~~~


一、lambda表達式概述

lambda 表達式是一種匿名函數,即沒有函數名的函數;該匿名函數是由數學中的λ演算而來的。通常情況下,lambda函數的語法定義爲:

[capture] (parameters) mutable ->return-type {statement}

意義:
[capture] :捕捉列表。捕捉列表總是作爲lambda的開始,即出現於lambda的開始處。它是lambda的引出符(即開始標誌)。編譯器可以根據該“標誌”來作出判斷出該函數是否爲lambda函數。同時“捕捉列表”能夠捕捉上下文中的變量以作爲lambda函數使用。
(parameters):參數列表。和C/C++中的普通函數參數意義一樣。該部分是可選的,意味着如果我們不需要進行參數傳遞時,可以連同括號“()”一起省略掉。
mutable:該關鍵字爲一個修飾符。在默認的情況下,lambda函數總是返回一個const喊,而當我們在參數列表後面註明了“mutable”關鍵字之後,則可以取消其常量性質。若在lambda中使用了mutable修飾符,則“參數列表”是不可省略掉的(即使是參數爲空)。
->return-type: 函數的返回值類型。和C/C++中的普通函數返回值類型的性質一樣。主要目的是用來追蹤lambda函數(有返回值情況下)的返回類型。若lambda函數不需要返回值,則可以直接將這部分省略掉。
{statement}:函數體。在該函數體中,除了可以使用參數列表中的變量外,還可以使用所有捕獲到的變量(即[capture] 中的變量)。

如圖:

在這裏插入圖片描述

對於匿名函數,一般用於傳函數參數,當然也可以直接定義調用.

		auto pfun=[]{cout<<"hello world"<<endl;}		//這裏使用auto自動判斷類型  其實是函數指針
		pfun();						//調用這個函數


二、捕獲列表

規則:

    []:什麼也不捕獲
    
    [=]:捕獲所有一切變量,都按值捕獲

    [&]:捕獲所有一切變量,都按引用捕獲

    [=, &a]:捕獲所有一切變量,除了a按引用捕獲,其餘都按值捕獲

    [&, =a]:捕獲所有一切變量,除了a按值捕獲,其餘都按引用捕獲

    [a]:只按值捕獲a

    [&a]:只按引用捕獲a

    [a, &b]:按值捕獲a,按引用捕獲b

1.[=]拷貝捕獲

#include <iostream>

using namespace std;

int main()
{
	int i = 1024;
	auto func = [=] {	// [=] 表明將外部的所有變量拷貝一份到該函數內部
		cout << i <<endl;
	};
	auto func2 = [] { //未指名捕獲, i 不存在
		cout << i<< endl;
	};
	func();
	return 0;
}

2.[&]引用捕獲

#include <iostream>

using namespace std;

int main()
{
	int i = 1024;
	cout << &i << endl;
	auto pfun = [&] {
		cout << &i << endl;
	};
	pfun();
	return 0;
}

3.[=, &] 拷貝與引用混合

#include <iostream>
using namespace std;
 
int main()
{
    int i = 1024, j = 2048;
 
    cout << "i:" << &i << endl;
    cout << "j:" << &j << endl;
 
    auto fun1 = [=, &i]{ // 默認拷貝外部所有變量,但引用變量 i
        cout << "i:" << &i << endl;
        cout << "j:" << &j << endl;
    };
    fun1();
	return 0;
}

結果
outside i:0x28ff0c
outside j:0x28ff08
inside i:0x28ff0c
inside j:0x28ff04

4.[bar] 指定引用或拷貝

#include <iostream>
using namespace std;
 
int main()
{
    int i = 1024, j = 2048;
 
    cout << "outside i value:" << i << " addr:" << &i << endl;
 
    auto fun1 = [i]{
        cout << "inside  i value:" << i << " addr:" << &i << endl;
        // cout << j << endl; // j 未捕獲
    };
    fun1();
}

結果:
outside i value:1024 addr:0x28ff08
inside i value:1024 addr:0x28ff04

#include <iostream>
using namespace std;
 
int main()
{
    int i = 1024, j = 2048;
 
    cout << "outside i value:" << i << " addr:" << &i << endl;
 
    auto fun1 = [&i]{
        cout << "inside  i value:" << i << " addr:" << &i << endl;
        // cout << j << endl; // j 未捕獲
    };
    fun1();
}

結果:
outside i value:1024 addr:0x28ff08
inside i value:1024 addr:0x28ff08

#include <iostream>
using namespace std;
 
int main()
{
    int i = 1024, j = 2048, k;
 
    cout << "outside i:" << &i << endl;
    cout << "outside j:" << &j << endl;
 
    auto fun1 = [i, &j]{
        cout << "inside  i:" << &i << endl;
        cout << "inside  j:" << &j << endl;
        // cout << k; // k 未捕獲
    };
    fun1();
}

結果:
outside i:0x28ff0c
outside j:0x28ff08
inside i:0x28ff00
inside j:0x28ff08

5.[this] 捕獲 this 指針

#include <iostream>
using namespace std;
 
class test
{
public:
    void hello() {
        cout << "test hello!n";
    };
    void lambda() {
        auto fun = [this]{ // 捕獲了 this 指針
            this->hello(); // 這裏 this 調用的就是 class test 的對象了
        };
        fun();
    }
};
 
int main()
{
    test t;
    t.lambda();
}

三、案例

#include <iostream>

using namespace std;

int main()
{
	int a = 1, b = 2;
	auto lambda = [](int a, int b) {
		b = a + a + a;
		return a + b;
	};
	cout<<lambda(a,b)<<endl;
	auto pFun = [] {
		cout << "hello lambda" << endl;
	};
	pFun();
	return 0;
}

四、lambda 表達式與function

C++11中,新增加了一個std::function對象,std::function對象是對C++中現有的可調用實體的一種類型安全的包裹(我們知道像函數指針這類可調用實體,是類型不安全的);關於function的介紹前面有響應的筆記;

直接看例子比較直接:

#include <iostream>
#include <functional>

using namespace std;

function<void(int)> pfun;

int main()
{
	pfun = [](int x){
		cout << "x:"<<x << endl;
	};
	pfun(3);
	return 0;
}

結果:

x:3

聲明function函數,返回值爲空,參數爲int型;類似函數指針,我們將值傳入即可


想了解學習更多C++後臺服務器方面的知識,請關注:
微信公衆號:C++後臺服務器開發

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