10.3.2 Lambda Expressions
10.3.2 Lambda Expressions
容器v存储了一组按照字符串长度排序的字符串,函数biggies实现以下功能:
void biggies(vector<string> &words, vector<string>::size_type sz)
{
//get an iterator to the first element whose size >= sz
// compute the number of elements with size >= sz
// print words of the given size or longer, each one followed by s space
}打印容器中大于等于给定字符长度的字符串
调用:
std::vector<std::string> words = {"a", "be", "can", "bed", "able", "again", "ability", "afternoon"};
biggies(words, 4);输出:
able again ability afternoon标准库中定义了find_if()algorithm 返回首个使得predicate 非0的元素的iterator,如果没有则返回end iterator。
由于predicate 的参数和 algorithm 有关,find_if()的predicate是unary,只能接收一个元素类型的参数,不能传递额外的size_type 参数。不能使用find_if() 查找 first element whose size >= sz。
Introducing Lambdas
callable object
[!quote]
An object or expression is callable if we can apply the call operator to it. That is, if e is a callable expression, we can write e(args) where args is comma-separated list of zero or more arguments.
凡是能够通过()进行调用的都属于callable object,包括但不限于以下类型:
- functions
- function pointers
- classes that overloaded the function-call operator
- 下面介绍的lambda expressions
定义 Lambda expression
[capture list] (parameter list) -> return type { function body}| 内容 | 是否必需 | 含义 | 说明 |
|---|---|---|---|
| capture list | 否(可以为空) | an list of local variables defined in the closing function. | 和普通函数不同的是,lambda 可能定义在函数内,如果要使用它所在的函数内的local variables 需要在capture list 中声明 |
| parameter list | 是 | same as in any ordinary function | 参数列表,不能带有默认实参 |
| return type | 否 | must use a trailing return to specify its return type. | 根据return 语句推断,如果没有return 则为void |
| function body | 是 | same as in any ordinary function |
使用示例
auto f = [] { return 42; }
cout << f() << endl; //prints 42| 行号 | 功能 | 说明 |
|---|---|---|
| 1 | defined f as a callable object | 如果lambda 要在函数内多个地方调用则将其赋值给一个对象 |
| 2 | call a lambda | 和函数调用的形式相同 |
Passing Arguments to a Lambda
[!quote]
A call to a lambda always has as many arguments as the lambda has parameters.
由于不能定义默认实参,所以传递给lambda 的实参和它所定义的形参一致。其他和普通函数一致。
使用lambda 判断两个字符串的长度
[] (const string &a, const string &b)
{ return a.size() < b.size(); }Using the Capture List
lambda 可以使用它所在的函数的local variables,但是需要在Capture List 中显式声明要使用的variables。
定义在 biggies()中 find_if( ) algorithm 要使用的lambda:
[sz] (const string &a)
{ return a.size() >= sz; }| 行号 | 功能 | 说明 |
|---|---|---|
| 1 | 捕获biggies(words, sz)中的局部变量sz | 和ordinary function的差别:除了parameter list 外还可以带有和使用环境相关的额外指定的参数。这样类型虽然还是 unary(parameter list 只有1个参数),但是实际使用的参数就没有限制了 |
| 2 | 第一个大于等于给定长度的元素predicate 返回true |
Calling find_if
在find_if 中使用lambda
auto wc = find_if(words.begin(), words.end(),
[sz] (const string &a)
{ return a.size() >= sz; }
);如果没有使lambda 返回true 的元素,则wc 和 words.end() 指向相同
The for_each Algorithm
[!quote]
This algorithm takes a callable object and calls that object on each element in the input range.
使用for() 遍历整个容器
使用for_each 对给定范围内的元素进行处理
for_each(wc, words.end(),
[] (const string &s)
{ cout << s << " "; }
);| 行号 | 功能 | 说明 |
|---|---|---|
| 3 | 打印字符串 | lambda 可以直接使用 local statics and variables declared outside the function directly。cout 定义在iostream 中,由头文件引入,相当于是outside the function,所以可以直接使用cout 进行打印 |
实现:
int outsideTheFunction = 3;
int main(int argc, char **argv)
{
static int localStatic = 5;
auto f = [argc] (char **v) {
std::cout << "capture variable argc:" << argc
<< "\nparameter v:" << v[0]
<< "\noutside:" << outsideTheFunction
<< "\nlocalStatic:" << localStatic << std::endl;
};
f(argv);
return 0;
}效果:
capture variable argc:1
parameter v:D:\Project\QtProject\Cpp_Primer\build\Qt_6_8_0_mingw_64-Debug\helloCpp.exe
outside:3
localStatic:5 static int localStatic = 5;
auto f = [localStatic] () {};报错:
main.cpp:13:15: 'localStatic' cannot be captured because it does not have automatic storage durationPutting It All together
整合一下,并对biggies()进行测试
实现:
using std::vector;
using std::string;
using std::cout;
using std::endl;
void biggies(vector<string> &words, vector<string>::size_type sz)
{
auto wc = find_if(words.begin(), words.end(),
[sz] (const string &a)
{ return a.size() >= sz; }
);
auto count = words.end() - wc;
cout << count << " words of length " << sz << " or longer\n";
for_each(wc, words.end(),
[] (const string &s)
{ cout << s << " "; }
);
cout << endl;
}
int main(int argc, char **argv)
{
vector<string> words = {"a", "be", "can", "bed", "able", "again", "ability", "afternoon"};
biggies(words, 4);
biggies(words, 7);
biggies(words, 10);
return 0;
}效果:
4 words of length 4 or longer
able again ability afternoon
2 words of length 7 or longer
ability afternoon
0 words of length 10 or longer