1. 定义
lambda是函数对象:编写一个lambda后,编译器会将该表达式转换成一个未命名类的未命名对象,类中含有一个重载的函数调用运算符。
eg.
stable_sort(words.begin(),words.end(),[](const string &a,const string &b)
{
return a.size() < b.size();});
//等价于下面的类:
class ShorterString{
public:
bool operator()(const string &a,const string &b)
{
return a.size() < b.size();}
};
stable_sort(words.begin(),words.end(),ShorterString());
测试代码:
std::vector<string> words = {
"a31", "b1" };
stable_sort(words.begin(), words.end(), [](const string& a, const string& b)
{
return a.size() < b.size(); });
for_each(words.begin(), words.end(), [](const string& s)
{
std::cout << s << endl; });
std::vector<string> words2 = {
"a31", "b1" };
stable_sort(words2.begin(), words2.end(), ShorterString());
for_each(words2.begin(), words2.end(), [](const string& s)
{
std::cout << s << endl; });
输出结果为
b1
a31
b1
a31
2. 表示 lambda 及相应捕获行为的类
lambda产生的类必须为每个值捕获的变量建立对应的数据成员,同时创建构造函数。
eg.
auto wc = find_if(words.begin(),words.end(),[sz](const string &a)
{
return a.size() > = sz;})
//该 lambda 表达式产生的类将形如:
class SizeComp
{
SizeComp(size_t n):sz(n) {
}
bool operator()(const string &s)const {
return s.size() >= sz;}
private:
size_t sz;
};
测试代码:
void lambda_functionObject_test2(vector<string>::size_type sz) {
std::vector<string> words = {
"a31", "b1" };
auto wc = find_if(words.begin(), words.end(), [sz](const string& a)
{
return a.size() >= sz; });
std::cout << *wc << endl;
auto wc2 = find_if(words.begin(), words.end(), SizeComp(sz));
std::cout << *wc2 << endl;
}
lambda_functionObject_test2(3);
输出结果:
a31
a31
3. 特性
- lambda默认不能改变它捕获的变量。在默认情况下,由lambda产生的类中的函数调用运算符是一个const成员函数。如果lambda被声明为可变的,则调用运算符就不再是const函数了。
- 通过引用捕获变量时,由程序负责确保lambda执行时该引用所绑定的对象确实存在。因此编译器可以直接使用该引用而无须在lambda产生的类中将其存储为数据成员。
- .通过值捕获的变量被拷贝到lambda中,此时lambda产生的类必须为每个值捕获的变量建立对应的数据成员,并创建构造函数,用捕获变量的值来初始化数据成员。
- .lambda产生的类不包含默认构造函数、赋值运算符和默认析构函数,它是否包含默认拷贝/移动构造函数则通常要视捕获的变量类型而定。
【引用】