首页 > 编程语言 >C++ Lambda表达式笔记

C++ Lambda表达式笔记

时间:2024-11-19 20:19:43浏览次数:1  
标签:std int 捕获 C++ vec lambda 表达式 Lambda

1. 什么是 Lambda 表达式?

Lambda 表达式是 C++11 引入的一种特性,允许定义匿名函数(没有名字的函数),并且可以像普通函数一样调用,甚至可以作为参数传递给其他函数。

基本语法:

[capture_list](parameters) -> return_type { function_body };
  • [capture_list]:捕获列表,决定外部变量如何被 lambda 捕获。
  • (parameters):参数列表,与普通函数的参数类似。
  • -> return_type(可选):返回类型,通常可以省略,由编译器自动推断。
  • { function_body }:函数体,包含要执行的具体逻辑。

2. Lambda 表达式的基本用法

  • 无参数、无返回值

    []() { std::cout << "Hello, Lambda!" << std::endl; }();
    

    输出:

    Hello, Lambda!
    
  • 有参数、返回值

    auto add = [](int a, int b) { return a + b; };
    std::cout << add(2, 3) << std::endl;  // 输出 5
    
  • 显式指定返回类型

    auto divide = [](int a, int b) -> double {
        return static_cast<double>(a) / b;
    };
    std::cout << divide(5, 2) << std::endl;  // 输出 2.5
    

3. 捕获列表([capture_list]

捕获列表决定 lambda 如何访问外部作用域中的变量。可以按值捕获或按引用捕获。

(1) 空捕获列表:[]
  • 不捕获任何外部变量。
  • 仅适用于 lambda 完全独立的情况。

示例:

auto print = []() { std::cout << "Independent Lambda" << std::endl; };
print();
(2) 按值捕获:[x]
  • 捕获外部变量 x 的副本,lambda 内的修改不会影响原变量。

示例:

int x = 5;
auto lambda = [x]() { std::cout << x << std::endl; };
lambda();  // 输出 5
x = 10;    // 修改原变量
lambda();  // 仍输出 5
(3) 按引用捕获:[&x]
  • 捕获外部变量 x 的引用,lambda 内的修改会影响原变量。

示例:

int x = 5;
auto lambda = [&x]() { x += 10; };
lambda();
std::cout << x << std::endl;  // 输出 15
(4) 捕获所有外部变量:[=][&]
  • [=]:按值捕获所有外部变量。
  • [&]:按引用捕获所有外部变量。

示例:

int x = 5, y = 10;
auto lambda1 = [=]() { std::cout << x + y << std::endl; };  // 按值捕获
auto lambda2 = [&]() { x += y; };                          // 按引用捕获
lambda1();  // 输出 15
lambda2();
std::cout << x << std::endl;  // 输出 15
(5) 混合捕获:[=, &x][&, x]
  • [=, &x]:按值捕获所有变量,但对 x 按引用捕获。
  • [&, x]:按引用捕获所有变量,但对 x 按值捕获。

示例:

int x = 5, y = 10;
auto lambda = [=, &y]() { y += x; };  // x 按值,y 按引用
lambda();
std::cout << y << std::endl;  // 输出 15

4. 使用 Lambda 表达式排序

Lambda 表达式经常用于自定义排序规则,例如在 std::sort 中。

  • 升序排序

    std::vector<int> vec = {5, 2, 9, 1};
    std::sort(vec.begin(), vec.end(), [](int a, int b) { return a < b; });
    // vec: {1, 2, 5, 9}
    
  • 降序排序

    std::sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; });
    // vec: {9, 5, 2, 1}
    
  • 复杂排序规则

    std::sort(vec.begin(), vec.end(), [](int a, int b) {
        if (a % 2 == b % 2) return a > b;  // 同为奇数或偶数,按降序
        return a % 2 < b % 2;              // 偶数优先
    });
    // 假设 vec = {5, 2, 4, 7, 8}
    // 排序后:{8, 4, 2, 7, 5}
    

5. Lambda 表达式的实际应用场景

  1. 代替普通函数:用于实现一次性的功能,减少定义单独函数的冗余。
  2. 自定义排序:灵活定义排序规则(如 std::sort)。
  3. 回调函数:用于事件响应或异步处理(如 std::for_each)。
  4. 函数式编程:与标准库的函数式接口(如 std::transform)结合使用。
  5. 捕获变量用于计算:简化闭包的实现。

6. 示例:捕获外部变量的高级应用

int base = 10;
auto multiplier = [base](int x) { return base * x; };

std::cout << multiplier(2) << std::endl;  // 输出 20
  • 捕获 base,并使用其值进行计算。
  • 这使得 lambda 可以与外部变量结合实现更多功能。

7. 总结

Lambda 表达式的优势:

  1. 简洁:减少了定义额外函数的冗余代码。
  2. 灵活:可以捕获外部变量,轻松实现闭包。
  3. 高效:与标准库算法结合(如 std::sortstd::transform),使代码更清晰。

常用模式:

  • 无捕获[]() {}
  • 按值捕获[x]() {}[=]() {}
  • 按引用捕获[&x]() {}[&]() {}
  • 混合捕获[=, &x][&, x]

Lambda 表达式是现代 C++ 编程的重要工具,值得熟练掌握!

标签:std,int,捕获,C++,vec,lambda,表达式,Lambda
From: https://www.cnblogs.com/lyx9785/p/18555520

相关文章

  • C++语言之多态
    多态是面向对象编程中的一个重要概念,它是指同一个行为具有多个不同表现形式或形态的能力。比如,在不同的类中可以定义同名的方法,这些方法可以根据对象的类型不同而执行不同的逻辑。多态可以通过继承和接口实现,在继承关系中,子类重写父类的方法,当使用父类引用指向子类对象时,调用......
  • 【一分钟学C++】动态库与静态库
    竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生~公众号:C++学习与探索 | 个人主页:rainInSunny | 个人专栏:LearnOpenGLInQt文章目录动态库常见格式特点加载方式静态库常见格式特点动态库和静态库中的符号导出常见问题动态库常见格式  动态库是一......
  • C++虚函数表
    一、概念在C++中,虚函数表(VirtualFunctionTable,简称vtable)是实现多态机制的一个重要底层数据结构。当一个类中包含了虚函数时,编译器会为这个类创建一个虚函数表,用来存放该类的虚函数的地址。每个包含虚函数的类的对象实例中,会隐含一个指针(通常称为虚指针,vptr),它指向所属类......
  • 什么是 C++ 中的友元函数和友元类?友元的作用是什么?有什么注意事项?
    友元函数定义友元函数是在类中声明的非成员函数,它可以访问类的私有(private)和保护(protected)成员。友元函数虽然不是类的成员函数,但它被授予了访问类内部成员的特殊权限。声明方式在类的定义中,使用friend关键字来声明友元函数。classMyClass{private:intprivateDat......
  • c++等级考试第8级第2卷
                                       道路(2024.3八级)代码#include<iostream>#include<algorithm>#include<cmath>#include<cstdio>#include<vector>#include<cstring>usingnamespacestd;st......
  • 【入门】字符串的反码c++
    #include<bits/stdc++.h>usingnamespacestd;intmain(){ //一、分析问题 //已知:一个长度不超过80个字符的字符串。 //未知:字符串的反码。 //关系:如果这是一个小写字符,则它和字符a的距离与它的反码和字符z的距离相同;如果是一个大写字符,则它和字符A的距离与它......
  • 在bug中巩固C++
    记录自己的各种报错,在错误中学习ing结构体全局变量的声明与初始化问题#include<iostream>usingnamespacestd;//声明一个结构体BooksstructBook{stringname;stringauthor;stringsubject;intid;//构造函数Book(stringname,stringa......
  • 【C++】十六进制数据的字节序排列问题、大小端
    十六进制数据的字节序排列问题,涉及到大小端(Endianness)的概念。包括它与大小端存储方式的关系。1.十六进制数据在内存中的存储定义的数据#defineFRAME_TYPE_PARAM_SET0x30010x3001是一个16位(2字节)整数。在内存中,0x3001的存储方式依赖于系统的字节序:小端......
  • C++编程:通过多线程与协程优化阻塞型任务的调度性能
    文章目录0.引言1.多线程VS多线程+协程1.1示例1:使用传统的多线程进行矩阵乘法1.2.示例2:使用协程优化阻塞型任务3.分析与对比0.引言我们知道:多线程:适用于处理计算密集型任务或IO操作较少的场景,但会因为线程切换和创建销毁的开销而影响性能。协程:适用于处......
  • 实验4 C++
    任务2:GradeCalc.cpp1#pragmaonce2#include<iostream>3#include<vector>4#include<string>5#include<algorithm>6#include<numeric>7#include<iomanip>89usingstd::vector;10usingstd::......