当前位置: 首页 > news >正文

(C++11/C++14新特性)C++中的Lambda表达式——捕获方式和参数?值捕获和引用捕获?泛型Lambda和普通Lambda?

作者:求一个demo

版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

内容通俗易懂,没有废话,文章最后是面试常问内容(建议通过标题目录学习)

废话不多说,我们直接开始------>>>>>>

一、Lambda表达式

        Lambda表达式是C++11引入的一种匿名函数特性,允许你在需要函数的地方内联定义函数,不需要单独声明和定义命名函数。

1、基本语法

      (1)Lambda表达书基本组成部分:

[capture](parameters) -> return_type { 
    // 函数体 
}

        ①capture:捕获子句,指定哪些外部变量可以在Lambda体内使用。

        ②parameters:参数列表(可选)。

        ③return_type:返回类型(可选,通常可以自动推导),这两种情况可以不写(无返回值;返回值可以被编译器推导)。

        ④函数体body:用于编写函数逻辑的地方。

        (2)Lambda表达式的底层是如何实现的?

        ①编译器生成一个匿名类。

        ②捕获的变量称为该类的成员变量

        ③重载了operator()。

2、捕获子句(捕获变量的几种方式)

        捕获子句(捕获列表)决定了Lambda表达式如何访问外部变量:

        ①[]:不捕获任何外部变量。

        ②[=]:以值捕获所有外部变量(包括this指针)。

        ③[&]:以引用捕获所有外部变量。

        ④[a,&b]:混合捕获,a以值捕获,b以引用捕获。

        ⑤[this]:捕获当前类的this指针。

        ⑥[=,&x]:默认以值捕获,但x以引用捕获。

        ⑦[&,x]:默认以引用捕获,但x以值捕获。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
    int x = 10;
    int y = 20;    
    // 简单的lambda表达式
    auto print = []() { cout << "Hello Lambda!\n"; };//
    print();//调用lambda这个函数
    
    // 带参数的lambda
    auto add = [](int a, int b) { return a + b; };
    cout << add(5, 3) << "\n";  // 输出8
    
    // 捕获外部变量
    auto capture = [x, &y]() {
        cout << "x: " << x << ", y: " << y << "\n";
        y++;  // 可以修改y,因为它是引用捕获
        // x++;  // 错误!x是值捕获,不能在函数内部修改
    };
    capture();
    cout << "y after capture: " << y << "\n";  // y被修改
    
    // 在STL算法中使用lambda
    vector<int> nums = {1, 5, 3, 4, 2};
    sort(nums.begin(), nums.end(), [](int a, int b) {
        return a > b;  // 降序排序
    });
    
    for (int n : nums) {
        cout << n << " ";
    }
    cout << "\n";
    
    // 可变lambda (允许修改值捕获的变量)
    auto mutable_lambda = [x]() mutable {
        x++;  // 可以修改,因为是mutable
        cout << "Inside mutable lambda: " << x << "\n";
    };
    mutable_lambda();
    cout << "Outside: " << x << "\n";  // 原x不变
    
    return 0;
}

3、按值捕获和按引用捕获

        (1)按值捕获:只可以输出内容,不可以对内容进行修改,捕捉列表中的变量为只读,是原变量的一份拷贝。如果按值捕获,并且想要修改拷贝的值,可以使用mutable关键字进行修饰(修改const修饰的变量也可以用mutable)。

auto mutable_lambda = [x]() mutable {
        x++;  // 可以修改,因为是mutable
        cout << "Inside mutable lambda: " << x << "\n";
    };

        (2)按引用捕获:获得该变量的引用,可以对该变量进行任何操作。

4、返回类型

        大多是情况下,编译器可以自动推导Lambda的返回值。但当函数体包含多个return语句且类型不同时,需要显示指定返回类型:

auto lambda = [](int x) -> double {//接收int类型参数,返回值类型为double类型(不写 -> double,编译器自动推导返回int类型)。
    if (x > 0) return 1.5;
    else return 2;//这里会隐式转换为double
};
auto lambda = [](int a, double b) { return a + b; };//返回更高精度的类型(double),此例属于普通lambda,int可以隐式转换为double。

二、区别(泛型Lambda表达式和普通Lambda表达式)

1、参数类型声明方式

        (1)普通Lambda(C++11):必须显示指定每个参数具体类型。

auto lambda = [](int a, double b) { return a + b; };

        (2)泛型Lambda(C++14):使用auto作为参数类型,编译器会根据实际调用推导类型。

auto lambda = [](auto a, auto b) { return a + b; };

2、模板机制

        (1)普通Lambda(C++11)

        ①相当于一个普通函数对象,参数类型固定。

        ②如果需要对不同类型操作,需要定义多个Lambda。

        (2)泛型Lambda(C++14)

        ①相当于一个函数模板(使用auto定义参数类型)。

        ②编译器会为每种调用参数组合生成相应的实例,例如可处理int+double等组合。

3、使用场景

        (1)普通Lambda(C++11)

        ①参数类型明确且固定的情况。

        ②需要明确控制参数类型时。

        (2)泛型Lambda(C++14)

        ①需要处理多种类型参数的时候。

        ②编写更通用的代码,特别是模板代码中。

        ③避免为不同的类型重复编写相似的Lambda。

4、实现原理

        (1)普通Lambda(C++11):编译器生成一个具有固定参数类型的函数调用运算符。

        (2)泛型Lambda(C++14):编译器生成一个模板化的函数调用运算符。

5、总结

        ①参数类型:普通Lambda必须显示指定;泛型Lambda可用auto自动推导。

        ②灵活性:普通Lambda只能处理固定类型;泛型Lambda可处理多种类型。

        ③实现方式:普通Lambda是普通函数对象;泛型Lambda是模板化函数对象。

        ④代码复用:普通Lambda需要为不同类型编写多个Lambda;泛型Lambda 可以一个Lambda处理多种类型。

        ⑤典型应用:普通Lambda适用于类型明确的简单操作;泛型Lambda适用于通用算法、模板代码。

三、校招面试常问内容

1、什么是Lambda表达式?优点是什么?

(1)什么是Lambda:匿名函数,可以在需要函数的地方内联定义。

(2)优点:代码简洁,捕获上下文变量方便。

2、Lambda表达式基本语法?

[capture](parameters) -> return_type { body }

捕获列表、参数列表、返回类型(可省略)、函数体。

3、Lambda的捕获列表有哪些?有什么区别?

        ①[]:不捕获任何外部变量。

        ②[=]:以值捕获所有外部变量(包括this指针)。

        ③[&]:以引用捕获所有外部变量。

        ④[a,&b]:混合捕获,a以值捕获,b以引用捕获。

        ⑤[this]:捕获当前类的this指针。

        ⑥[=,&x]:默认以值捕获,但x以引用捕获。

        ⑦[&,x]:默认以引用捕获,但x以值捕获。

4、值捕获和引用捕获的区别?

        ①值捕获:创建时拷贝变量,内部不能修改(使用mutable进行内部修改,不影响外部)。

        ②引用捕获:直接使用外部变量,内部修改会影响外部。

5、普通Lambda和泛型Lambda的区别?

        ①参数类型:普通Lambda必须显示指定;泛型Lambda可用auto自动推导。

        ②灵活性:普通Lambda只能处理固定类型;泛型Lambda可处理多种类型。

        ③实现方式:普通Lambda是普通函数对象;泛型Lambda是模板化函数对象。

        ④代码复用:普通Lambda需要为不同类型编写多个Lambda;泛型Lambda 可以一个Lambda处理多种类型。

        ⑤典型应用:普通Lambda适用于类型明确的简单操作;泛型Lambda适用于通用算法、模板代码。

6、Lambda表达式的底层是如何实现的?

        ①编译器生成一个匿名类。

        ②捕获的变量称为该类的成员变量

        ③重载了operator()。

7、Lambda和函数指针的区别?

        ①Lambda可以有状态(捕获变量),函数指针无状态。

        ②Lambda更灵活,可内联定义。

        ③无捕获的Lambda可(隐式)转换为函数指针。

// 定义一个函数指针类型
using FuncPtr = int(*)(int, int);

int main() {
    // 无捕获的 Lambda 表达式
    auto lambda = [](int a, int b) {
        return a + b;
    };
    // 将 Lambda 表达式转换为函数指针
    FuncPtr funcPtr = lambda;
    // 使用函数指针调用
    int result = funcPtr(3, 5);
    cout << "Result: " << result << endl;

    return 0;
}

8、如何在类成员函数中使用Lambda?

        捕获this指针访问成员。

class MyClass {
    void func() {
        auto lambda = [this](){ this->memberFunc(); };
    }
};

最后,如有不足和错误的地方,期待私信指正!

相关文章:

  • 一文解读DeepSeek大模型在政府工作中具体的场景应用
  • C++初阶知识复习 (31~45)
  • jQuery 入门案例教程
  • Ubuntu系统Docker安装失败
  • VUE如何前端控制及动态路由详细讲解
  • 日程公布| 第八届地球空间大数据与云计算前沿大会与集中学习(3号通知)
  • idea自动生成注释
  • 传奇类网游页游2.5D游戏场景地图素材Eagle库 沙漠沙海隔壁
  • Visual Studio | 性能探测器
  • Vscode 更换插件下载位置
  • 相机租赁网站基于Spring Boot SSM
  • 数据处理专题(四)
  • Java基础概念汇总
  • JavaScript 学习笔记
  • 【Yolov8部署】 VS2019+opencv-dnn CPU环境下部署目标检测模型
  • MyBatis--简单测试
  • arinc818 fpga单色图像传输ip
  • MySQL DQL,数据查询语言的用法
  • 小智机器人关键函数解析,Application::OutputAudio()处理音频数据的输出的函数
  • Unity LOD Group动态精度切换算法(基于视锥+运动速度)技术详解
  • weirdcore制作网站/自己怎么建网站
  • 自己做网站步骤 域名/人力资源短期培训班
  • 影响网站显示度的原因/百度网盘怎么找资源
  • 做网站公司怎么赚钱/商丘seo教程
  • asp 公司网站/友情链接样式
  • 云南 网站建立/淘宝客推广一天80单