/*
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;
}
*/
来源: http://www.bubuko.com/infodetail-2578150.html