C++11中lambda、std::function和std:bind详解

2020-01-06 16:42:25王振洲

c/softtech/ostool/48219.html">color: #ff0000">前言

在C++11新标准中,语言本身和标准库都增加了很多新内容,本文只涉及了一些皮毛。不过我相信这些新特性当中有一些,应该成为所有C++开发者的常规装备。本文主要介绍了C++11中lambda、std::function和std:bind,下面来一起看看详细的介绍吧。

lambda 表达式

C++11中新增了lambda 表达式这一语言特性。lambda表达式可以让我们快速和便捷的创建一个”函数”。

下面是lambda表达式的语法:


[ capture-list ] { body }
[ capture-list ] ( params ) { body }
[ capture-list ] ( params ) -> ret { body }
[ capture-list ] ( params ) mutable exception attribute -> ret { body }

这其中:

- capture-list 是需要捕获的变量列表,用逗号分隔。其详细说明见下文。 - params 是lambda表达式需要的参数列表,写法和函数参数一样,不过这里不支持默认参数。 - ret 指明了lambda表达式的返回值。通过return语句,如果编译器能够推断出返回值的类型。或者表达式没有返回值,“-> ret”可以省略。 - body 函数体。 - mutable 当捕获列表是以复制(见下文)的形式捕获时,默认这些复制的值是const的,除非指定了mutable。 - exception 提供了异常的说明。 - attribute 对于attribute的描述可以参见这里:http://www.easck.com/w/cpp/language/attributes,这里不多说明。

下面,我们通过经典的Hello World示例来看一下lambda表达式:


auto lambda1 = [] {std::cout << "Hello, World!n";};
lambda1();

这个lambda表达式将打印出字符串“Hello, World!”。

同时,我们将这个表达式赋值给“lambda1”这个变量,然后像调用函数一样,调用这个lambda表达式。

使用lambda表达式,可以让我们省却定义函数的麻烦,以inline的方式写出代码,这样的代码通常更简洁。
并且,由于阅读代码时不用寻找函数定义,这样的代码也更易读。

下面,我们来看另外一个例子。这个例子的需求是:

分两次,打印出一个vector集合中,所有:

1. 模 5 = 0

2. 大于 20

的数字。

现假设已有这个集合的定义如下:

vector<int> numbers { 1, 2, 3, 4, 5, 10, 15, 20, 25, 35, 45, 50 };

我们最先想到的方法自然是定义两个函数,分别按照上面的要求打印出需要的数字,它们的定义如下:


void printNumber1(vector<int>& numbers) {
 for (const int& i : numbers) {
 if (i % 5 == 0) {
 cout<<i<<endl;
 }
 }
}

void printNumber1(vector<int>& numbers) {
 for (const int& i : numbers) {
 if (i % 5 == 0) {
 cout<<i<<endl;
 }
 }
}