C++ 新特性 | C++ 11 | lambda表达式

一、lambda表达式

1、简介

是一个匿名函数 ,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数 ,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。闭包就是能够读取其他函数内部变量的函数,可以理解成"定义在一个函数内部的函数"。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。C++中的Lambda表达式从C++11开始引入,完整的声明如下:

cpp 复制代码
[capture] (params) -> returnType { body }

后面主要说明捕获形参返回类型函数体与具名函数的定义一致,没有区别。一个简单的Lambda表达式应用场景,如下:

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
int main()
{
    vector<int> vec{ 3, 4 };
    //降序排序
    sort(vec.begin(), vec.end(), [](int a, int b) {return a > b; });
    for (size_t i = 0; i < vec.size(); i++)
    {
        cout << vec[i] << endl;
    }
}

2、创建一个有名称的lambda表达式

lambda表达式创建的匿名函数,但是可以给这个匿名的函数起个名字,例如:

cpp 复制代码
#include <iostream>
using namespace std;
 
auto add = [](int x, int y)->int{
    return x + y;
};
 
int main(){
    int x = 10, y = 20;
    cout << add(x, y);
    return 0;
}

注意:不同于常规的函数,可以在函数的内部定义有名称的lambda表达式,add的实际类型随实现而异,它取决于编译器使用什么类型来跟踪lambda。

3、返回类型

如果没有指定返回类型,lambda表达式的返回类型从 return 语句推导,下面两行代码是等价的:

cpp 复制代码
//降序排序(不指定返回类型)
sort(vec.begin(), vec.end(), [](int a, int b) {return a > b; });
//降序排序(指定返回类型,没有返回值时可以指定为void类型)
sort(vec.begin(), vec.end(), [](int a, int b) -> int {return a > b; });

4、捕捉

捕捉讲的是lambda表达式引用外部变量的方法,下面是常见的几种捕捉方式:

  • [ ]表示不捕捉任何变量
  • [=]表示按值传递的方法捕获父作用域的所有变量
  • [&]表示按引用传递的方法捕获父作用域的所有变量
  • [=, &a]表示按值传递的方法捕获父作用域的所有变量,但按引用传递的方法捕获变量a
  • [&, a]表示按引用传递的方法捕获父作用域的所有变量,但按值传递的方法捕获变量a

5、lambda表达式的应用

定义一个Number类,这个类的vector类型的成员num保存一些数字,这个类包含一个模板函数,这个函数返回在num里面可以被指定值N整除的元素的数目。例如,num = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10},N = 3;则函数返回的是在数组num里面可以被3整除的元素的数目。此时,如果在类里面针对每一个N都声明一个成员函数,这个类会变得非常庞大。因此,我们在这里声明一个函数模板,把一个函数作为参数传给这个模板函数,如下:

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;

class Number{
private:
    vector<int> num;
public:
    Number(int numSize = 10){
        for(int i = 1; i < numSize; i ++){
            num.push_back(i);
        }
    }

    template<typename Func>
    int findNumbers(Func func){
        int len = 0;
        for(vector<int>::iterator itr = num.begin(); itr != num.end(); itr ++){
            if(func(*itr)){
                len ++;
            }
        }
        return len;
    }
};

// 定义一个函数
bool isValid(int val){
    return val % 3 == 0;
}

// 定义一个函数符
class FuncMode{
private:
    int dv;
public:
    FuncMode(int dv):dv(dv){}
    bool operator()(int x){
        return x % dv == 0;
    }
};

int main()
{
    // 使用函数指针
    Number N(10);
    cout << N.findNumbers(isValid) << endl;

    // 使用函数符
    FuncMode func(3);
    cout << N.findNumbers(func) << endl;

    // 使用lambda表达式
    cout << N.findNumbers([](int x){return x % 3 == 0;}) << endl;

    return 0;
}

输出结果:

cpp 复制代码
3
3
3

Process returned 0 (0x0)   execution time : 0.606 s
Press any key to continue.
相关推荐
xmh-sxh-13144 分钟前
常用的前端框架有哪些
java
volcanical4 分钟前
线性回归与逻辑回归
算法·逻辑回归·线性回归
yonuyeung7 分钟前
代码随想录算法【Day4】
算法
老马啸西风8 分钟前
NLP 中文拼写检测纠正论文 A Hybrid Approach to Automatic Corpus Generation 代码实现
java
云边有个稻草人9 分钟前
AIGC与虚拟身份及元宇宙的未来:虚拟人物创作与智能交互
笔记·算法·aigc
小蒜学长10 分钟前
基于Spring Boot的宠物领养系统的设计与实现(代码+数据库+LW)
java·前端·数据库·spring boot·后端·旅游·宠物
L.S.V.10 分钟前
Java 溯本求源之基础(三十一)——泛型
java·开发语言
Redamancy_Xun17 分钟前
开源软件兼容性可信量化分析
java·开发语言·程序人生·网络安全·测试用例·可信计算技术
IDRSolutions_CN24 分钟前
(教程)用 Java 从 PDF 中提取嵌入的文件
java·经验分享·pdf·软件工程·团队开发
海波东27 分钟前
单例模式懒汉式、饿汉式(线程安全)
java·安全·单例模式