C++11 lambda表達式使用場景解析

Lambda表達式的使用場景

其實我在剛開始使用lambda的時候就挺好奇什麼時候使用好,經常在不需要使用的時候使用上了,真的是多此一舉,那麼要在什麼情況下使用呢?
因爲lambda表達式又叫匿名函數(當然我們也可以理解爲是一個未命名的內聯函數),那麼肯定就跟函數掛上關係了,通常情況寫你在編程的時候需要將這段代碼封裝到一個函數裏面再來調用,那這個時候就避免不了想函數名了,其實有時候取名字真的是件麻煩事,有時腦子突然短路都不知道命什麼名字好了,那麼這個時候你就要想起我們的lambda表達式了,它可以很好的幫你解決命名困難症這個問題。
那麼還有什麼情況下可以去考慮使用lambda表達式呢?在你的整個項目編程中,你獨立出來一個函數,但這個函數實現相對簡單並且可能在整個項目只使用了一次(即不存在複用的情況),那麼這個時候我們就可以考慮使用下lambda表達式了,這樣可以讓代碼更加緊湊,更加容易維護,下面我們來看看lambda表達式的簡單運用。

Lambda表達式的簡單應用

先看看lambda表達式變量截取的方式

  • [] 不截取任何變量
  • [&] 截取外部作用域中所有變量,並作爲引用在函數體中使用
  • [=] 截取外部作用域中所有變量,並拷貝一份在函數體中使用
  • [=, &foo] 截取外部作用域中所有變量,並拷貝一份在函數體中使用,但是對foo變量使用引用
  • [bar] 截取bar變量並且拷貝一份在函數體重使用,同時不截取其他變量
  • [this] 截取當前類中的this指針。如果已經使用了&或者=就默認添加此選項。

場景一:

我們在做算法題的時候經常會遇到一個問題,比較兩個數的大小,第一個數比第二個數大的時候返回true,反之返回false。

我們先來寫下我們傳統的解決辦法:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

bool compare(int& a, int& b)
{
    return a > b;
}

int main(void)
{
    int data[6] = { 3, 4, 12, 2, 1, 6 };
    vector<int> testdata;
    testdata.insert(testdata.begin(), data, data + 6);

    // 排序算法
    sort(testdata.begin(), testdata.end(), compare);    // 升序

    return 0;
}

有沒覺得這段代碼太簡單了,然而我們這種方法卻還給他取了個名字,名字都佔了整個函數的大部分字母了,但是別怕,我們有lambda表達是呢,下面來看看我們的lambda表達式的解法:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main(void)
{
    int data[6] = { 3, 4, 12, 2, 1, 6 };
    vector<int> testdata;
    testdata.insert(testdata.begin(), data, data + 6);

    sort(testdata.begin(), testdata.end(), [](int a, int b){ return a > b; });

    return 0;
}

場景二

使用auto來接收一個lambda表達式,當然我們也可以直接使用C++11裏面的新特性function來接收lambda表達式,兩者等價的,因爲auto是自動類型轉換,所以在某些場合使用起來更方便。

溫馨提示:對function不大瞭解的讀者可以到網上查找相關資料,function的頭文件爲 “functional”。

#include <iostream>
#include <functional>
using namespace std;

int main(void)
{
    int x = 8, y = 9;
    auto add = [](int a, int b) { return a + b; };
    std::function<int(int, int)> Add = [=](int a, int b) { return a + b; };

    cout << "add: " << add(x, y) << endl;
    cout << "Add: " << Add(x, y) << endl;

    return 0;
}

最終的運行結果都是:17
解析: function中的第一個int是返回值類型,括號裏面的兩個int都是函數的參數類型。

場景三

使用lambda表達式來實現遞歸算法
我大概的解釋下這個的遞歸題目:已知f(1)=1,f(2)=2,那麼請實現f(n)=f(n-1)+f(n-2),此處的n>2
這不明顯的遞歸算法嗎?太簡單了。

#include <iostream>
#include <functional>
using namespace std;

int main(void)
{
    std::function<int(int)> recursion = [&recursion](int n) { 
        return n < 2 ? 1 : recursion(n - 1) + recursion(n - 2); 
    };

    // 我們來檢測下我們的結果
    cout << "recursion(2):" << recursion(2) << endl;
    cout << "recursion(3):" << recursion(3) << endl;
    cout << "recursion(4):" << recursion(4) << endl;

    return 0;
}

運行結果:

recursion(2):2  
recursion(3):3  
recursion(4):5 

解析:爲什麼這裏我們不使用auto呢?因爲會報錯,它會提示你使用auto類型說明符聲明的變量不能出現在自己的初始值設定項中,我個人認爲因爲auto是自動類型轉換的,如上面的例子它需要靠lambda表達式的返回值才能確認recursion的類型,因此在先執行lambda表達式的時候是無法識別recursion的類型的,所以這裏使用auto會報錯,這裏是我個人的理解,因爲個人的能力有限,也不知道這樣解釋對不對,如果不對,歡迎大牛們給小弟指點一二。

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