C++的lamda表达式,不用就忘记了
(2018-10-21 15:44:40)分类: 计算技术 |
lamda表达式,在python中也有,简单地说就是匿名函数。关于lamda表达式的例子和详细用法,我们可以参考这:http://en.wikipedia.org/wiki/Anonymous_function#C.2B.2B
C++11提供了对匿名函数的支持,称为Lambda函数(也叫Lambda表达式).
Lambda表达式具体形式如下:
[capture](parameters)->return-type{body}
capture:需要用到的外部变量,parameters:函数参数;body:函数体
如果没有参数,空的圆括号()可以省略.返回值也可以省略,如果函数体只由一条return语句组成或返回类型为void的话.形如:
[capture](parameters){body}
下面举了几个Lambda函数的例子:
[](int
x, int y) { return x + y; } // 隐式返回类型
[](int&
x) { ++x; }
[a](int&
x) { x+=a; }
[]()
{ ++global_x; }
[]{
++global_x; }
[](int
x, int y) -> int { int z = x + y; return z; }
在这个例子中创建了一个临时变量z来存储中间值.
和普通函数一样,这个中间值不会保存到下次调用.
什么也不返回的Lambda函数可以省略返回类型,
而不需要使用
-> void 形式.
Lambda函数可以引用在它之外声明的变量.
这些变量的集合叫做一个闭包.
闭包被定义在Lambda表达式声明中的方括号[]内.
这个机制允许这些变量被按值或按引用捕获.下面这些例子就是:
[]
[x, &y]
[&]
[=]
[&, x]
[=, &z]
接下来的两个例子演示了Lambda表达式的用法.
std::vector < int > some_list;
int total = 0;
for (int i=0;i<5;++i) some_list.push_back(i);
std::for_each(begin(some_list), end(some_list), [&total](int x)
{
});
此例计算list中所有元素的总和.
变量total被存为lambda函数闭包的一部分.
因为它是栈变量(局部变量)total的引用,所以可以改变它的值.
std::vector < int > some_list;
此例中total会存为引用,
value则会存一份值拷贝.
对this的捕获比较特殊,
它只能按值捕获.
this只有当包含它的最靠近它的函数不是静态成员函数时才能被捕获.对protect和priviate成员来说,
这个lambda函数与创建它的成员函数有相同的访问控制.
如果this被捕获了,不管是显式还隐式的,那么它的类的作用域对Lambda函数就是可见的.
访问this的成员不必使用this->语法,可以直接访问.
不同编译器的具体实现可以有所不同,但期望的结果是:按引用捕获的任何变量,lambda函数实际存储的应该是这些变量在创建这个lambda函数的函数的栈指针,而不是lambda函数本身栈变量的引用.
不管怎样,
因为大数lambda函数都很小且在局部作用中,
与候选的内联函数很类似,
所以按引用捕获的那些变量不需要额外的存储空间.
如果一个闭包含有局部变量的引用,在超出创建它的作用域之外的地方被使用的话,这种行为是未定义的!
lambda函数是一个依赖于实现的函数对象类型,这个类型的名字只有编译器知道.
如果用户想把lambda函数做为一个参数来传递,
那么形参的类型必须是模板类型或者必须能创建一个std::function类似的对象去捕获lambda函数.使用
auto关键字可以帮助存储lambda函数,
class CTest
{
public:
private:
cout<<[]()->int
分析:
(1)里面有两个lamda函数,并且无名namda函数直接被执行了,没有用变脸存储
(2)最外面的lamda函数是:
[]()->int
{
(3)然后for()循环中,也有个lamda函数,这个lamda函数由于后面也跟了个(),因此也被直接执行了
[&]()
{
}
(4)最后输出的结果:4950