前面介绍了函数对象,其优点在于解决函数指针无法保存状态数据的问题。
但如果在程序中大量使用函数对象,则会使代码非常累赘而冗长。
所以为了解决这问题,STL提供了Lambda表达式。
Lambda表达式可以方便地使用应用于STL中,对算法进行自定义,同时在可以访问Lambda表达式之外的数据,解决函数执行过程中状态数据的保存问题。
代码如下:
// 3.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//定义student类
class Student
{
public:
Student()
{
m_strName = "";
m_nHeight = 0;
}
public:
Student( string strName, int nHeight)
: m_strName(strName), m_nHeight(nHeight)
{
}
string GetName()
{
return m_strName;
}
int GetHeight()
{
return m_nHeight;
}
private:
string m_strName;
int m_nHeight;
};
int _tmain(int argc, _TCHAR* argv[])
{
vector<Student> vecStu;
Student st1( "zhouzhou", 180 );
Student st2( "xiaoxiao", 162 );
Student st3( "huhu", 176 );
vecStu.push_back(st1);
vecStu.push_back(st2);
vecStu.push_back(st3);
int nTotalHeight = 0;
int nCount = 0;
for_each( vecStu.begin(), vecStu.end(),
[&]( Student st )
{
nTotalHeight += st.GetHeight();
++nCount;
});
cout<<nCount<<"个学生的平均身高是:"<<(float)nTotalHeight/nCount<<endl;
return 0;
}
相比之前的函数对象,明显简单些。
Lambda表达式的定义:
【变量使用说明符号】(参数列表) -> 返回值数据类型
{
//函数体
}
其中【】表示Lambda表达式的开始,在中括号中,可以使用使用lambda表达式定义当前作用域中的变量方式。如果是传值(复制)方式,则使用【=】表示,它
将使得lambda表达式以只读的方式访问 当前作用域中的变量。如果中括号是空白,默认情况下也表示以传值方式使用当前作用域内的变量。
vector<int> v;
v.push_back(5);
v.push_back(6);
v.push_back(7);
int nAdd = 3;
for_each(v.begin(), v.end(),
[=](int x)
{
x += nAdd; //这里nAdd则为当前作用域中的变量,如果【=】则不能更改nAdd变量。
cout<<x<<endl;
});
如果想改当前作用域变量的值,则【=】换成【&】来替代即可。
vector<int> v;
v.push_back(5);
v.push_back(6);
v.push_back(7);
int nTotal = 0;
for_each(v.begin(), v.end(),
[&](int x)
{
nTotal += x;
cout<<nAdd<<endl;
});
注意这里输出的结果:5 11 18
nTotal保存了vector容器中所有数据的总和,实现了从Lambda表达式向外部传递数据的功能。
如果需要传递多个数据,则可以在【】的第一位设置一个默认的传递方式,然后再分别制定各个变量的传递方式。
例如,在默认情况下使用传引用的方式,但其中一个变量使用传值的方式,可以这样定义:
vector<int> v;
v.push_back(5);
v.push_back(6);
v.push_back(7);
int nTotal = 0;
int nAdd = 3;
for_each(v.begin(), v.end(),
[&, nAdd](int x) //默认采用传引用访问,nAdd使用传值访问
{
nTotal += x * nAdd;
cout<<nTotal<<endl;
});
通常Lambda表达式没有返回值,如果需要,则可以用->来返回一个值。
int nCount = count_if(v.begin(), v.end(),
[=](int x) -> bool
{
return x % 2 == 0;
});
关于Lambda表达式的复用:
在vector和list中,同时应用,而不用分别写lambda表达式。
vector<int> v;
v.push_back(5);
v.push_back(6);
v.push_back(7);
list<int> L;
L.push_back(1);
L.push_back(2);
L.push_back(3);
auto show = [=]( int x )
{
cout<<x<<endl;
};
for_each(v.begin(), v.end(), show);
for_each(L.begin(), L.end(), show);