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

C++实用指南:Lambda 表达式的妙用

Lambda 表达式的灵活性和强大功能确实为编程提供了许多便利。但是我们发现许多开发者仍然无法灵活运用其便利,于是写了这篇文章。

Lambda 允许我们编写更简洁和灵活的代码。例如在处理网络请求时,我们经常需要确保响应与当前的状态或需求仍然相关。通过捕获上下文变量,Lambda 表达式可以帮助我们在处理异步回调时简化逻辑。

网络请求

案例1:通过捕获 i64RequestIndex 实现丢弃过期的请求回包
在第一个案例中,我们通过捕获请求索引 i64RequestIndex 来确保只处理最新的网络请求。如果请求索引与保存在对象中的最后一个请求索引相匹配,则我们可以确定这是最新的请求,并且可以安全地处理响应。如果索引不匹配,表明在此请求和响应之间,已经发起了新的请求,因此当前的响应已经过时,可以被丢弃。

// 成员变量:用于记录请求序号
int m_myLastRequestIndex = 0;// 发送网络请求并处理响应
uint64_t i64RequestIndex = ++m_myLastRequestIndex;
core::network::Send(request, [=](Rsp rsp) {if (this->m_myLastRequestIndex == i64RequestIndex) {// 只处理与最后一次请求索引匹配的响应}},nullptr);

案例2:合并请求以减少后台压力
第一个案例可能会发起很多无效请求。因此,在第二个案例中,我们不仅要检查请求是否为最新的,还需要考虑合并请求。当多个相似的请求在短时间内发起时,我们可以选择等待第一个请求的响应,然后根据需要决定是否发起新的请求。这种方式可以减轻服务器的压力,并提高应用程序的性能。

// 成员变量:用于跟踪是否有正在进行的请求
bool m_isRequestPending = false;
bool m_isNeedNewRequest = false;// 发起请求的包装函数
auto sendRequest = [&]() {m_isRequestPending = true;core::network::Send( request, [=](Rsp rsp) {m_isRequestPending = false;if (m_isNeedNewRequest ) {m_isNeedNewRequest  = false;sendRequest();// 需要再次发起请求} else {// 处理最后一次请求的响应}},nullptr);
};// 逻辑判断是否需要发起请求
if (m_isRequestPending ) {// 如果当前已经有一个请求在进行,则等待这个请求的响应m_isNeedNewRequest = true;
} else {// 如果当前没有请求正在进行,则发起新的请求sendRequest();
}

在这个例子中,我们使用一个布尔变量 m_isRequestPending 来跟踪是否有请求正在进行。如果有请求正在进行,我们就等待该请求完成。在请求的回调中,我们将 isRequestPending 设置为 false 以表示请求已完成,并在必要时发起新的请求。

更多场景

1. 延迟执行(Lazy Evaluation)

Lambda 可以用来实现延迟计算,这允许代码仅在需要时才执行相关计算。这在优化性能和资源使用方面非常有用。

auto lazyValue = [expensiveComputation]() { return expensiveComputation(); };
// expensiveComputation 不会立即执行,直到调用 lazyValue()auto result = lazyValue(); // 在这里实际执行计算

2. 作为回调(Callbacks)

Lambda 经常用作回调函数,尤其是在 GUI 编程或事件驱动编程中。这允许开发者在同一处代码内部即定义事件行为,也提供了更好的上下文管理。

button->onClick([this](){ this->doSomething(); });

3. 作为函数对象(Functors)

Lambda 可以替代传统的函数对象(functors),简化语法并提高代码的可读性。

std::sort(vec.begin(), vec.end(), [](int a, int b) { return a < b; });

4. 作用域保护(Scope Guard)

Lambda 可以用来实现作用域保护模式,确保退出作用域时自动执行特定的清理代码。

auto guard = scope_guard([&] { cleanUpResources(); });

5. 实现装饰器模式(Decorator Pattern)

可以使用 Lambda 表达式来实现装饰器模式,动态地添加功能。

auto withLogging = [](auto func) {return [=](auto... args) {logBefore(args...);auto result = func(args...);logAfter(result);return result;};
};auto decoratedFunction = withLogging(someFunction);

6. 线程封闭(Thread Encapsulation)

在启动新线程时,Lambda 可以用来封装要在线程中运行的代码,从而使得创建线程的代码更加简洁。

std::thread t([=] { doWork(); });
t.join();

7. 实现状态机(State Machines)

Lambda 可以存储在容器中,使得状态转换和事件处理更加灵活。

std::map<State, std::function<void(Event)>> stateMachine;
stateMachine[State::INIT] = [](Event e) { /* 处理 INIT 状态的事件 */ };

8. 自定义迭代行为(Custom Iteration)

Lambda 可以与算法结合使用,以实现自定义的迭代行为。

std::for_each(collection.begin(), collection.end(), [](auto& item) { processItem(item); });

Lambda 表达式由于其匿名和内联特性,对于创建简洁、灵活的代码非常有用,它们已经成为现代C++编程中不可或缺的工具。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C#中的字符串
  • vue3前端开发-小兔鲜项目-使用pinia插件完成token的本地存储
  • 推荐一款前端滑动验证码插件(Vue、uniapp)
  • C++设计模式--单例模式
  • Java人力资源招聘社会校招类型招聘系统PC端
  • Linux服务管理(四)Apache服务
  • <Python><paddle>基于python使用百度paddleocr实现车牌识别
  • Vue2从基础到实战(指令修饰符)详解
  • Golang | Leetcode Golang题解之第290题单词规律
  • 便携移动工作站,端侧 AI 大模型设备折腾笔记:ROG 幻 X 和 4090 扩展坞
  • Python常用内置库介绍
  • Redis学习[3] ——持久化
  • android(安卓)最简单明了解释版本控制之MinSdkVersion、CompileSdkVersion、TargetSdkVersion
  • Python基础知识笔记——random模块
  • C++包管理之`vcpkg`简介
  • 【Linux系统编程】快速查找errno错误码信息
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • ES6系列(二)变量的解构赋值
  • Fastjson的基本使用方法大全
  • Flannel解读
  • gitlab-ci配置详解(一)
  • Java 23种设计模式 之单例模式 7种实现方式
  • JavaScript设计模式系列一:工厂模式
  • Linux Process Manage
  • log4j2输出到kafka
  • MD5加密原理解析及OC版原理实现
  • Python爬虫--- 1.3 BS4库的解析器
  • Redis 中的布隆过滤器
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • WePY 在小程序性能调优上做出的探究
  • 彻底搞懂浏览器Event-loop
  • 从重复到重用
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 前端临床手札——文件上传
  • 日剧·日综资源集合(建议收藏)
  • 一些关于Rust在2019年的思考
  • # .NET Framework中使用命名管道进行进程间通信
  • #etcd#安装时出错
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (07)Hive——窗口函数详解
  • (160)时序收敛--->(10)时序收敛十
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (2)nginx 安装、启停
  • (39)STM32——FLASH闪存
  • (4)logging(日志模块)
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (八)Spring源码解析:Spring MVC
  • (二)丶RabbitMQ的六大核心
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (回溯) LeetCode 40. 组合总和II