1、方法介绍与使用
C++ 11 引入了 lambda 表达式,以允许我们编写一个内联函数,该函数可用于无法重用且不值得命名的短代码片段。最简单的 lambda 表达式可以定义如下:
[ capture clause ] (parameters) -> return-type
{
definition of method
}
通常 lambda 表达式中的 return-type 由编译器本身评估,我们不需要显式指定和 -> return-type 部分可以忽略,但在一些复杂的情况下,如条件语句,编译器无法确定返回类型,我们需要指定。
1 capture list
是一个lambda所在函数中定义的局部变量的列表,通常为空;
2 return type
返回值类型;
可忽略,使用自动推倒;
尾置返回类型;就是用 ->后面跟类型 来表示函数的返回类型,这样更直观;
3 parameter list
参数列表;
可忽略,自动推倒;
4 function body
函数体;
其中carpture是捕获列表,params是参数,opt是选项,ret则是返回值的类型,body则是函数的具体实现。
补充说明:
[ capture ] ( params ) opt -> ret { body; };
1.捕获列表描述了lambda表达式可以访问上下文中的哪些变量。
[] :表示不捕获任何变量
[=]:表示按值捕获变量
[&]:表示按引用捕获变量
[this]:值传递捕获当前的this
但是捕获列表不允许变量的重复传递:例如
[=,x]
上面这种捕获是不允许的,=表示按值的方式捕获所有的变量,x相当于被重复捕获了。
2.params表示lambda的参数,用在{}中。
3.opt表示lambda的选项,例如mutable,后面会介绍一下mutable的用法。
4.ret表示lambda的返回值,也可以显示指明返回值,lambda会自动推断返回值,
但是值得注意的是只有当lambda的表达式仅有一条return语句时,自动推断才是有效的。
参考来源:https://blog.csdn.net/weixin_43055404/article/details/103299156
案例1:
#include <iostream>
using namespace std;
int main()
{
int a = 5,b = 6;
auto f = [=]{return a+b;};//[=]按值捕获了a和b
cout << f() << endl;
return 0;
}
运行程序输出结果为11,由上栗看出可以给lambda指定一个名称,再用该名称来取代调用该表达式。
案例2:
#include <iostream>
using namespace std;
int main()
{
int a = 5;
auto f1 = [=]{return a+1;};//按值捕获a
auto f2 = [&]{return a+1;};//按引用捕获a
cout << f1() << endl;
cout << f2()<< endl;
a++;
cout << f1() << endl;
cout << f2() << endl;
return 0;
}
结果:
6
6
6
7
2、demo应用
下面给出了具有标准函数的 lambda 表达式的各种用法:
// C++ program to demonstrate lambda expression in C++
#include <bits/stdc++.h>
using namespace std;
// Function to print vector
void printVector(vector<int> v)
{
// lambda expression to print vector
for_each(v.begin(), v.end(), [](int i)
{
std::cout << i << " ";
});
cout << endl;
}
int main()
{
vector<int> v {4, 1, 3, 7, 2, 3, 1, 17};
printVector(v);
// below snippet find first number greater than 4
// find_if searches for an element for which
// function(third argument) returns true
vector<int>:: iterator p = find_if(v.begin(), v.end(), [](int i){return i > 4;});
//寻找满足以下条件的元素 第一个元素就是输出
cout << "First number greater than 4 is : " << *p << endl;
// function to sort vector, lambda expression is for sorting in
// non-increasing order Compiler can make out return type as
// bool, but shown here just for explanation
sort(v.begin(), v.end(), [](const int& a, const int& b) -> bool
{
return a > b;//倒顺序
});
printVector(v);
// function to count numbers greater than or equal to 5
int count_5 = count_if(v.begin(), v.end(), [](int a)
{
return (a >= 5);
});
cout << "The number of elements greater than or equal to 5 is : "
<< count_5 << endl;
// function for removing duplicate element (after sorting all
// duplicate comes together)
p = unique(v.begin(), v.end(), [](int a, int b)
{
return a == b;
});
// printVector(v);
cout << "去掉重复的数 : "<<endl;
// resizing vector to make size equal to total different number
v.resize(distance(v.begin(), p)); //计算去掉后的数组的元素个数,并重新排列大小
printVector(v);
// accumulate function accumulate the container on the basis of
// function provided as third argument
int arr[] = {1, 2, 3, 4, 5};
int f = accumulate(arr, arr + 5, 1, [](int i, int j){return i * j;});
cout << "Factorial of 5 is : " << f << endl;// 将数组的元素相乘,这里类似阶乘计算,如果数字没有顺序就是正常的元素相乘
// We can also access function by storing this into variable
auto square = [](int i)
{
return i * i;
};
cout << "Square of 5 is : " << square(5) << endl;
}
执行结果:
4 1 3 7 2 3 1 17
First number greater than 4 is : 7
17 7 4 3 3 2 1 1
The number of elements greater than or equal to 5 is : 2
去掉重复的数 :
17 7 4 3 2 1
Factorial of 5 is : 720
Square of 5 is : 25
其中:用到的函数
unique的作用是从输入序列中“删除”所有相邻的重复元素。
distance() 函数用于计算两个迭代器表示的范围内包含元素的个数.
accumulate带有三个形参:头两个形参指定要累加的元素范围,第三个形参则是累加的初值。accumulate函数将它的一个内部变量设置为指定的初始值,然后在此初值上累加输入范围内所有元素的值。accumulate算法返回累加的结果,其返回类型就是其第三个实参的类型。
这里补充accumulate案例用法:
#include <vector>
#include <numeric>
#include <functional>
#include <iostream>
using namespace std;
int main( )
{
vector <int> v1, v2( 20 );
vector <int>::iterator Iter1, Iter2;
int i;
for ( i = 1 ; i < 21 ; i++ )
{
v1.push_back( i );//给向量数组 赋值
}
cout << "最初向量v1中个元素的值为:\n ( " ;
for ( Iter1 = v1.begin( ) ; Iter1 != v1.end( ) ; Iter1++ )
cout << *Iter1 << " ";
cout << ")." << endl;
// accumulate函数的第一个功能,求和
int total;
total = accumulate ( v1.begin ( ) , v1.end ( ) , 0 );
cout << "整数从1到20的和为: "
<< total << "." << endl;
// 构造一个前n项和的向量
int j = 0, partotal;
for ( Iter1 = v1.begin( ) + 1; Iter1 != v1.end( ) + 1 ; Iter1++ )
{
partotal = accumulate ( v1.begin ( ) , Iter1 , 0 );
v2 [ j ] = partotal;
j++;
}
cout << "前n项和分别为:\n ( " ;
for ( Iter2 = v2.begin( ) ; Iter2 != v2.end( ) ; Iter2++ )
cout << *Iter2 << " ";
cout << ")." << endl << endl;
// accumulate函数的第二个功能,计算连乘积
vector <int> v3, v4( 10 );
vector <int>::iterator Iter3, Iter4;
int s;
for ( s = 1 ; s < 11 ; s++ )
{
v3.push_back( s );
}
cout << "向量v3的初始值分别为:\n ( " ;
for ( Iter3 = v3.begin( ) ; Iter3 != v3.end( ) ; Iter3++ )
cout << *Iter3 << " ";
cout << ")." << endl;
//相乘,没有遍历
int ptotal;
ptotal = accumulate ( v3.begin ( ) , v3.end ( ) , 1 , multiplies<int>( ) );
cout << "整数1到10的连乘积为: "
<< ptotal << "." << endl;
// 构造一个前n项积的向量 相乘,开始遍历
int k = 0, ppartotal;
for ( Iter3 = v3.begin( ) + 1; Iter3 != v3.end( ) + 1 ; Iter3++ ) {
ppartotal = accumulate ( v3.begin ( ) , Iter3 , 1 , multiplies<int>( ) );
v4 [ k ] = ppartotal;
k++;
}
cout << "前n项积分别为:\n ( " ;
for ( Iter4 = v4.begin( ) ; Iter4 != v4.end( ) ; Iter4++ )
cout << *Iter4 << " ";
cout << ")." << endl;
}
执行结果:
最初向量v1中个元素的值为:
( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ).
整数从1到20的和为: 210.
前n项和分别为:
( 1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 210 ).
向量v3的初始值分别为:
( 1 2 3 4 5 6 7 8 9 10 ).
整数1到10的连乘积为: 3628800.
前n项积分别为:
( 1 2 6 24 120 720 5040 40320 362880 3628800 ).
补充:continue语句 可以使用该语句应用与上面的方法中
作用:
在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环
#include <iostream>
using namespace std;
int main() {
for (int i = 0; i < 20; i++)
{
if (i % 2 == 0)
{
continue;
//如果条件为真则继续循环,否则将值传递给吓一语句i
}
cout << i << endl;
}
// system("pause");
return 0;
}
执行结果:
1
3
5
7
9
11
13
15
17
19
参考
http://www.noobyard.com/article/p-gxpewbej-n.html
https://www.oracle.com/cn/servers/technologies/howto-use-lambda-exp-cpp11.html
https://blog.csdn.net/weixin_43055404/article/details/103299156