这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战
不知道大家在写代码时有没有遇到过这种情况:有时需要用到一个内容非常少的一个函数,比如在调用排序算法时std::sort,先暂停下,在这里先简单讨论下sort
std::sort是C++标准库算法文件里的一个排序算法(快速排序(不完全是)),复杂度为O(N·log(N))(不一定是这个,可能还会恶化到n^2),扯远了,下面说下sort的几个参数,sort其中一个函数重载如下:
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
其中first与last可以理解为容器要排序的范围,即起始位置以及结束位置;而comp为一个比较函数或者仿函数的名字,sort了解到这即可;
如果我们就为一个参数去定义一个函数或者定义一个仿函数,那也太麻烦了,于是lambda在这里就体现了优点;具体好在哪里呢?看如下代码:
std::vector<int> c={1,2,3,4,5,6,7,8,9};
bool compare(int a,int b){//这里只是简单写下,还可能更复杂
return a>b;
}
sort(c.begin(),c.end(),compare);
std::vector<int> c={1,2,3,4,5,6,7,8,9};
sort(c.begin(),c.end(),[](int a,int b){return a>b;});
两段代码一对比是不是精简了好多,而且更清晰,更明了,更简洁。
好了好了,该说说Lambda了
Lambda
Lambda的具体格式如下:
各个参数表达意思如下:
1、capture list表示捕获列表,就是捕获什么外部变量,捕获方式是什么,下文看例子一点就通。
2、parameter list参数列表,和函数一样,可有可无。
3、return type返回类型,可有可无。
4、function body函数体
示例:
auto f1 = [](int a) -> int { return a + 1; };
auto f2 = []() { return 2; };
cout << f1(1) << " " << f2() << endl;
捕获列表具体说明:
| 格式 | 说明 |
|---|---|
| [] | 不捕捉任何变量 |
| [&] | 捕获外部作用域中所有变量,并作为引用在函数体内使用 (按引用捕获) |
| [=] | 捕获外部作用域所有变量,在函数内内有个副本使用,拷贝的副本在匿名函数体内部是只读的 |
| [=,&x] | 按值捕获外部作用域中所有变量,并按照引用捕获外部变量x |
| [x] | 按值捕获 x变量,同时不捕获其他变量 |
| [&x] | 按引用捕获 x变量,同时不捕获其他变量 |
| [this] | 捕获当前类中的 this 指针,让 lambda 表达式拥有和当前类成员函数同样的访问权限,如果已经使用了 & 或者 =, 默认添加此选项 |
注意:
1、可以忽略参数列表和返回类型,但必须包含捕获列表和函数体,示例:auto f = [] { return 2; };
2、使用值拷贝的方式捕获外部变量,可读不能写,示例: int a=8888;auto f = [=] {return a++; };
3、如果不指定 lambda 表达式的返回值,编译器会根据 return 语句自动推导返回值的类型,
但需要注意的是 labmda表达式不能通过列表初始化自动推导出返回值类型,示例auto f = [] {return {1,3}}; };4、可以使用
std::function和std::bind来存储和操作lambda表达式。
对于注意的第二点,因为在C++2.0中lambda表达式会被看成一个仿函数,即operator()重载(),按照C++标准,operator()的默认属性是const的,一个const成员函数是无法修改成员变量值的,可以采用mutable 取消 operator () 的 const 属性。示例如下:
int a=8888;auto f = [=] ()mutable {return a=a+1; };
对于注意的第四点,示例如下:
#include <iostream>
#include <functional>
int main(void)
{
// 包装可调用函数
std::function<int(int)> f1 = [](int a) {return a; };
// 绑定可调用函数
std::function<int(int)> f2 = bind([](int a) {return a; }, placeholders::_1);//placeholders::_1绑定的参数/占位符
// 函数调用
std::cout << f1(100) << std::endl;
std::cout << f2(200) << std::endl;
return 0;
}
好啦,今天文章就到这里了,相信大家会收获满满;