• 为了保证你在浏览本网站时有着更好的体验,建议使用类似Chrome、Firefox之类的浏览器~~
    • 如果你喜欢本站的内容何不Ctrl+D收藏一下呢,与大家一起分享各种编程知识~
    • 本网站研究机器学习、计算机视觉、模式识别~当然不局限于此,生命在于折腾,何不年轻时多折腾一下

C++11之lambda详解

C++ admin 4年前 (2015-05-30) 1665次浏览 0个评论 扫描二维码

引言

先说几句题外话:对于初学 C++的人来说可能看到 lambda 的介绍之后基本上都没有足够的耐心去看,因为涉及到匿名函数的操作,而我们经常接触到都是确定的函数(有着明确的函数名,当然包含函数句柄的操作),当然自己在一开始学习的时候也是碰到这样的情况,所以现在回想起来还是有必要好好的记录下对 lambda 理解。

Lambda

首先我们要知道为什么需要 lambda,否则看完这篇文章都不知道何去何从。下面是我理解的 lambda 的用途:

– .在算法头文件包含了许多方便使用的函数(例如 for_each,transform),这些函数的操作参数中会调用相应自定义的函数句柄实现用户自定义处理。

– .对于类中的部分短小成员函数实现可以使用 lambda,这会是的代码量较少,方便阅读。

基本概念

lambda 的概念起源于函数编程,自身属于匿名函数编程。

基本的语法定义如下:

[ capture ] ( params ) mutable exception attribute -> ret { body }    (1)
[ capture ] ( params ) -> ret { body }    (2)
[ capture ] ( params ) { body }    (3)
[ capture ] { body }    (4)

解释:

1. capture -> 函数参数类型
2. params -> 操作符重载函数参数
3. mutuble 和 exception -> 修饰符:mutuble 表示传进来的参数可以被修改,对于传值的情况只会修改参数的 copy,而不会修改参数本身,exception 涉及到异常情况的处理。
4. ->ret 表示返回参数的类型
5. body 表示匿名函数的实体部分

对于 capture 的类型主要包含以下方面:

1、空。没有使用任何函数对象参数。

2、=函数体内可以使用 Lambda 所在作用范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。

3、&函数体内可以使用 Lambda 所在作用范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)。

4、this。函数体内可以使用 Lambda 所在类中的成员变量。

5、=,a 将 a 按值进行传递。按值进行传递时,函数体内不能修改传递进来的 a 的拷贝,因为默认情况下函数是 const 的。要修改传递进来的 a 的拷贝,可以添加 mutable 修饰符。

6、&a 将 a 按引用进行传递。

7、a,&b。将 a 按值进行传递,b 按引用进行传递。

8、=,&a,&b。除 a 和 b 按引用进行传递外,其他参数都按值进行传递。

9、&,a,b。除 a 和 b 按值进行传递外,其他参数都按引用进行传递。

实验代码

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
class lambda_id
{
public:
lambda_id() :m_data(20){};
void lambda_test()
{
std::vector<int> v;
v.push_back(1);
v.push_back(2);
//capture 为空
for_each(v.begin(), v.end(), [](int vec){std::cout << vec << endl; });
//capture 为=
int num = 1;
for_each(v.begin(), v.end(), [=](int vec){std::cout << vec + num << endl; });
//capture 为& mutable 表示传递的值可以被修改
int num_1 = 1;
for_each(v.begin(), v.end(), [&](int vec)mutable{std::cout << vec + num_1 << endl; num_1++; });
//capture 为 this
for_each(v.begin(), v.end(), [this](int vec)mutable{std::cout << vec + m_data << endl; });
//capture 为 res
int res = 5;
for_each(v.begin(), v.end(), [res](int vec)mutable{std::cout << vec << endl; res++;  });
std::cout << res << endl;
//capture 为=,&res1
int res1 = 5;
for_each(v.begin(), v.end(), [=, &res1](int vec){std::cout << vec << endl; ++res1; });
std::cout << res1 << endl;

}
private:
int m_data;
};
int _tmain(int argc, _TCHAR* argv[])
{
lambda_id result;
result.lambda_test();
return 0;
}

实验结果如下:

下面给出指定函数返回类型和异常操作 example(来源于 MSDN):

#include <iostream>
#include <functional>

int main()
{
using namespace std;

// The following code declares a lambda expression that returns
// another lambda expression that adds two numbers.
// The returned lambda expression captures parameter x by value.
auto addtwointegers = [](int x) -> function<int(int)> {
return [=](int y) { return x + y; };
};

// The following code declares a lambda expression that takes another
// lambda expression as its argument.
// The lambda expression applies the argument z to the function f
// and multiplies by 2.
auto higherorder = [](const function<int(int)>& f, int z) {
return f(z) * 2;
};

// Call the lambda expression that is bound to higherorder.
auto answer = higherorder(addtwointegers(7), 8);

// Print the result, which is (7+8)*2.
cout << answer << endl;//结果为 30
}

异常处理代码:

#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
// Create a vector that contains 3 elements.
vector<int> elements(3);

// Create another vector that contains index values.
vector<int> indices(3);
indices[0] = 0;
indices[1] = -1; // This is not a valid subscript. It will trigger an exception.
indices[2] = 2;

// Use the values from the vector of index values to
// fill the elements vector. This example uses a
// try/catch block to handle invalid access to the
// elements vector.
try
{
for_each(indices.begin(), indices.end(), [&](int index) {
elements.at(index) = index;
});
}
catch (const out_of_range& e)
{
cerr << "Caught '" << e.what() << "'." << endl;
};
}

`输出:

Caught 'invalid vector<T> subscript'.`

Deeplearn, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明C++11 之 lambda 详解
喜欢 (0)
admin
关于作者:
互联网行业码农一枚/业余铲屎官/数码影音爱好者/二次元

您必须 登录 才能发表评论!