C++11中的Lambda表达式

简介:

“Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。

ISO C++ 11 标准的一大亮点是引入Lambda表达式。基本语法如下:

[capture list] (parameter list) ->return type { function body } 

其中除了“[ ]”(其中捕获列表可以为空)和“复合语句”(相当于具名函数定义的函数体),其它都是可选的。它的类型是唯一的具有成员operator()的非联合的类类型,称为闭包类型(closure type)。

C++中,一个lambda表达式表示一个可调用的代码单元。我们可以将其理解为一个未命名的内联函数。

它与普通函数不同的是,lambda必须使用尾置返回来指定返回类型。

例如:调用<algorithm>中的std::sort,ISO C++ 98 的写法是要先写一个compare函数:

bool compare(int &a, int &b)
{
    return a > b;  //降序排序
}

然后,再这样调用:

sort(a, a + n, compare);

然而,用ISO C++ 11 标准新增的Lambda表达式,可以这么写:

sort(a, a + n, [](int a, int b){return a > b;});   //降序排序

这样一来,代码明显简洁多了。

由于Lambda的类型是唯一的,不能通过类型名来显式声明对应的对象,但可以利用auto关键字和类型推导:

auto f = [](int a, int b){return a > b;});

和其它语言的一个较明显的区别是Lambda和C++的类型系统结合使用,如:

autof = [x](int a, int b){return a > x;});//x被捕获复制
int x = 0,y = 1;
auto g = [&](int x){return ++y;});//y被捕获引用,调用g后会修改y,需要注意y的生存期
bool(*fp)(int, int) = [](int a, int b){return a > b;});//不捕获时才可转换为函数指针

Lambda表达式可以嵌套使用。

即将出版的ISO C++14支持基于类型推断的泛型lambda表达式。上面的排序代码可以这样写:

sort(a, a + n, [](const auto &a, const auto &b){return a > b;});//降序排序:不依赖a和b的具体类型

因为参数类型和函数模板参数一样可以被推导而无需和具体参数类型耦合,有利于重构代码;和使用auto声明变量的作用类似,它也允许避免书写过于复杂的参数类型。特别地,不需要显式指出参数类型使使用高阶函数变得更加容易。

下面举一个简单使用Lambda表达式的例子:

#include<iostream>
#include<algorithm>
#include<vector>
#include<ostream>
using namespace std;
int main()
{
    vector<int> v;
    for (int i = 0; i < 10; i++){
        v.push_back(i);
    }
    for_each(v.begin(), v.end(), [](int n){cout << n << " "; });
    cout << endl;
    return 0;
}

Lambda表达式默认的返回类型为void

为了对比,下面使用函数对象实现相同功能的代码:

#include<iostream>
#include<algorithm>
#include<vector>
#include<ostream>
#include<cassert>
using namespace std;

class LambdaFunctor{
public:
    void operator()(int n) const{
        cout << n << " ";
    }
};

int main()
{
    vector<int> v;
    for (int i = 0; i < 10; i++){
        v.push_back(i);
    }
    for_each(v.begin(), v.end(), LambdaFunctor());
    cout << endl;
    return 0;
}

对比一下,就会发现使用Lambda表达式要简洁得多

上面提到的Lambda表达式可以操作所在作用域的变量,这需要通过被称为“捕获”的特殊语法来实现,就是通过在[]内列出将要捕获的“外部”变量列表,这样在函数体内就可以访问并操作这些变量。参考下面的代码:

#include<iostream>
#include<algorithm>
#include<vector>
#include<ostream>
#include<cassert>
using namespace std;

int main()
{
    vector<int> v;
    for (int i = 0; i < 10; i++){
        v.push_back(i);
    }
    //使用for_each语句和Lambda表达式来实现对偶元素的计数

    int evenCount = 0;
    for_each(v.begin(), v.end(), [&evenCount](int n){
        cout << n;
        if (n % 2 == 0) {
            cout << " is even" << endl;
            evenCount++;
        }
        else {
            cout << " is odd" << endl;
        }
    });
    cout << "There are " << evenCount << " even numbers in the vector." << endl;
    getchar();
    return 0;
}
目录
相关文章
|
6天前
|
算法 编译器 C++
【C++11】lambda表达式
C++11 引入了 Lambda 表达式,这是一种定义匿名函数的方式,极大提升了代码的简洁性和可维护性。本文详细介绍了 Lambda 表达式的语法、捕获机制及应用场景,包括在标准算法、排序和事件回调中的使用,以及高级特性如捕获 `this` 指针和可变 Lambda 表达式。通过这些内容,读者可以全面掌握 Lambda 表达式,提升 C++ 编程技能。
30 3
|
3月前
|
算法 编译器 程序员
C++ 11新特性之Lambda表达式
C++ 11新特性之Lambda表达式
17 0
|
5月前
|
安全 编译器 C++
C++一分钟之-泛型Lambda表达式
【7月更文挑战第16天】C++14引入泛型lambda,允许lambda接受任意类型参数,如`[](auto a, auto b) { return a + b; }`。但这也带来类型推导失败、隐式转换和模板参数推导等问题。要避免这些问题,可以明确类型约束、限制隐式转换或显式指定模板参数。示例中,`safeAdd` lambda使用`static_assert`确保只对算术类型执行,展示了一种安全使用泛型lambda的方法。
65 1
|
6月前
|
算法 编译器 C++
C++一分钟之—Lambda表达式初探
【6月更文挑战第22天】C++的Lambda表达式是匿名函数的快捷方式,增强函数式编程能力。基本语法:`[capture](params) -&gt; ret_type { body }`。例如,简单的加法lambda:`[](int a, int b) { return a + b; }`。Lambda可用于捕获外部变量(值/引用),作为函数参数,如在`std::sort`中定制比较。注意点包括正确使用捕获列表、`mutable`关键字和返回类型推导。通过实践和理解这些概念,可以写出更简洁高效的C++代码。
55 13
|
6月前
|
C++
C++语言的lambda表达式
C++从函数对象到lambda表达式以及操作参数化
|
6月前
|
C++
C++一分钟之-理解C++的运算符与表达式
【6月更文挑战第18C++的运算符和表达式构成了编程的基础,涉及数学计算、逻辑判断、对象操作和内存管理。算术、关系、逻辑、位、赋值运算符各有用途,如`+`、`-`做加减,`==`、`!=`做比较。理解运算符优先级和结合律至关重要。常见错误包括优先级混淆、整数除法截断、逻辑运算符误用和位运算误解。解决策略包括明确优先级、确保浮点数除法、正确使用逻辑运算符和谨慎进行位运算。通过实例代码学习,如 `(a &gt; b) ? &quot;greater&quot; : &quot;not greater&quot;`,能够帮助更好地理解和应用这些概念。掌握这些基础知识是编写高效、清晰C++代码的关键。
37 3
|
6月前
|
C语言 C++ 容器
c++primer plus 6 读书笔记 第五章 循环和关系表达式
c++primer plus 6 读书笔记 第五章 循环和关系表达式
|
6月前
|
计算机视觉 C++
【见微知著】OpenCV中C++11 lambda方式急速像素遍历
【见微知著】OpenCV中C++11 lambda方式急速像素遍历
52 0
|
6月前
|
C++
C++ lambda表达式
C++ lambda表达式
|
4天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
18 2