1. 程式人生 > >C++新特性 lambda

C++新特性 lambda

不想 str temp 地址 不能 默認 當前 () 其他

/*
C++新特性:
lambda表達式:是C++新特性最終要之一,實際上是提供了
一個類似匿名函數的特性,而匿名函數則是在需要的一個函數
,但是又不想費力去命名一個函數的情況下去使用的。
[捕獲列表](參數列表)mutable(可選)異常屬性->返回類型{
//函數體
}
上面的語法規則除了[捕獲列表]內的東西外,其他部分都很好理解,
只是一般函數的函數名被濾去,返回值使用了->的形式進行。
所謂捕獲列表,其實可以理解為參數的一種類型,lambda表達式
內部函數體在默認情況下是不能夠使用函數體外部的變量的,
這時候捕獲列表可以起到傳遞外部數據的作用。根據傳遞的行為,
捕獲列表也分為以下幾種:
1、值捕獲:與參數傳值類似,值捕獲的前期變量可以拷貝,不同之處
在於,被捕獲的變量在lambda表達式被創建拷貝,而非調用時候才拷貝:
void learn_lambda_func_1(){
int value_1 = 1;
auto copy_value_1 = [value_1]{
return value_1;
} ;
value_1 = 100;
auto stored_value_1 = copy_value_1();
//這時候,stored_value_1 == 1,而value_1 == 100
//因為,copy_value_1 在創建的時候就保存了了一份value_1 的拷貝。
我們使用auto來自動獲取func的類型,這個非常重要。定義好lambda函數之後,
就可以當這場函數來使用了。
其中[]表示接下來開始定義lambda函數,中括號中間有可能會有參數,
之後的()填寫的是lambda函數的參數列表{}中間就是函數體了。
lambda函數的用處:假如設計了一個地址簿的類。現在要提供函數查詢
這個地址簿,可能根據姓名查詢,可能根據地址查詢,還有可能兩者結合
,要是為這些情況都寫一個函數,那麽很麻煩。所以我們應該提供一個接口,能方便的讓用戶自己定義自己的
查詢方式。
*/
#include<iostream>
#include <string>
#include <vector>

class AddressBook{
public:
template<typename func>
std::vector<std::string> findMatchAddress(func a)
{
std::vector<str::string> resaults;
for (auto iter = _address.begin(); iter != _address.end(); ++iter)
{
if (func(*iter)){
resaults.push_back(*iter);
}
}
return resaults;
}
private:
std::vector<std::string>_address;
};

/*
我們可以發現上面findMatchAddresses函數提供的參數是funcc類型,
這是一個泛型類型。在使用過程中應該傳入一個函數,,然後分別對
地址簿中的每一個entry執行這個函數,如果返回值為真那麽表明這個
entry符合使用者的篩選要求,那麽就應該放入結果當中,那麽這個func
類型的參數如何傳入?
*/
AddressBook gloabl_address_book;

std::vector<std::string> findAddressesFromOrgs(){
std::vector<std::string> a;
[](const std::string & addr){
return addr.find(".org") != std::string::npos;
};
return a;
}

/*
可以看到,我們在調用函數的時候直接定義了一個lambda函數。其參數類型是:
const string& addr
返回值是bool類型。
如果用戶要使用不同的方式查詢的話,只要定義不同的lambda函數就可以了。
*/


void learn_lambda_func_1(){
int value_1 = 1;

auto func = [] {
std::cout << "hello world" << std::endl;
};

func();

auto copy_value_1 = [value_1]
{
return value_1;
};
value_1 = 100;
auto store_value_1 = copy_value_1();
std::cout << store_value_1 << std::endl;
std::cout << value_1 << std::endl;
return;

}

int main(){
learn_lambda_func_1();
system("pause");
std::string name;
std::cin >> name;
return gloabl_address_book.findMatchAddress{
[&](const std::string& str){
return name.find(addr) != string::npos;
};
}
return 0;
}

/*lambda函數中的變量讀取,上述列子中,
lambda函數使用的都是函數使用的都是函數體的參數和它內部的信息,
並沒有使用外部信息。我們設想,從鍵盤讀取一個名字,然
後用lambda函數定義一個匿名函數,在地址簿中查找有沒有
相同名字的人。那麽這個lambdaa函數勢必就要能使用外部
block中的變量,所以我們就得使用變量截取功能。
(variable capture),從上述代碼中看出,我們的lambda函數已經能使用外部作用域
中的變量name,這個lambda函數一個最大的區別是[]中間加入了&符號,
這就是要告訴編譯器,要進行變量截取。這樣lambda函數體就可以使用
外部變量。如果不加入任何符號,編譯器就不會進行變量截取。
下面是各種變量截取的選項:
[]不截取
[&]截取外部作用域中的所有變量,並作為引用在函數體內使用
[=]截取外部作用域中的所有變量,並拷貝一份在函數體中使用
[=, &foo] 截取外部作用域中所有變量,並拷貝一份在函數體中使用,但是對foo變量使用引用
[bar] 截取bar變量並且拷貝一份在函數體重使用,同時不截取其他變量
[this] 截取當前類中的this指針。如果已經使用了&或者=就默認添加此選項。
*/

/*
lambda函數和STL
lambda函數的引入為STL的使用提供了極大地方便,


using namespace std;
v.push_back(1);
v.push_back(2);
//,,,
for (auto iter = v.begin(); iter != v.end(); ++iter){
cout << *iter << endl;
}
//現在有了lambda函數你可以這麽寫:
vector<int> v;
v.push_back(1);
v.push_back(2);
//...
for_each(v.begin(), v.end(), [](int val)){
cout << val << endl;
}
*/

C++新特性 lambda