C++ Lambda表达式中的捕获列表


0 前言

最近通过内部换组来到了新的开发组,组里核心业务用的是C++17,并且十分注重性能和资源的优化。我作为一个C++小白,趁着年底没有太多工作、下一年的项目也还没有启动的空档,看代码之外也花了些时间阅读C++书籍,希望能系统地学习这门语言。

最近在看项目代码时发现Lambda表达式在我们的代码中很常见,正好今天在阅读C++ Primer的时候读到了C++ Lambda的介绍,它在用法上和Java很相似,但有一个要素在Java的lambda表达式中很少特意提出来讲,那就是变量的捕获。这篇文章主要是想简单地总结一下C++ Lambda表达示的捕获列表的概念和用法。

1 Lambda表达式简介

在C++在11及之后的版本中支持了lambda表达式,它是一种像函数一样可调用的对象,就和匿名的inline function差不多。一个简单的lambda表达式的主要由返回类型、参数列表、捕获列表和方程体组成,可以表示为

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

关于Lambda表达式的更多内容,我会在以后的文章中多写学习笔记和自己的理解,这里先不赘述,先来看看捕获列表这个概念。

2 捕获列表(Capture List)

尽管Lambda表达式常常会被用在一个函数里,但它只能访问外部的全局变量而并不能访问函数里的局部变量,而这个捕获列表就是这Lambda表达式提供一个函数内的局部变量列表,只要被列在了列表内,那么表达式都可以对其进行访问。Lambda会将这些变量信息和自身放在一起,通常我们把它们这个整体叫作闭包(enclosure)。

一般来说,捕获变量的方式主要有两种:按值捕获(capture by value)和按引用捕获(capture by reference),不同的捕获方式不仅仅是让lambda表达式访问变量的方式不同,还由于它们在编译上的差别,它们对程序的限制也有所不同。这里为了方便也为了和C++ Primer的讲述方式一致,我将它们分为三大类来讲:

  • 按值捕获(capture by value)
  • 按引用捕获(capture by reference)
  • 隐式捕获(implicit captures)

2.1 按值捕获

和传递变量里的传递变量值类型相似,这种捕获方式捕获的也是变量的值,在编译期间,会在Lambda表达式被创建的时候把这个变量复制给局部的一个临时变量,所以这种捕获方式的变量必须是可以被复制的变量。比如在以下的例子中,我们将函数内的整型变量v1按值放入捕获列表中来让Lambda表达式能够访问其变量值:

#include <iostream>

Lambda 表达式中,捕获列表用于指定要捕获的外部变量。捕获列表可以包含以下 3 种方式: 1. 捕获捕获值可以通过在捕获列表中指定变量的方式来完成。在捕获值时,Lambda 表达式会在创建时将指定的变量复制一份,并在函数体中使用这份副本。例如: ```c++ int x = 1; auto func = [x]() { std::cout << x << std::endl; }; ``` 在上面的代码中,Lambda 表达式通过捕获值的方式来捕获变量 x。在 Lambda 表达式中使用的变量 x 是一个拷贝,对其进行修改不会影响原有的变量 x。 2. 捕获引用 捕获引用可以通过在捕获列表中指定变量的方式来完成。在捕获引用时,Lambda 表达式会在创建时将指定的变量的引用传递给函数体。例如: ```c++ int x = 1; auto func = [&x]() { std::cout << x << std::endl; }; ``` 在上面的代码中,Lambda 表达式通过捕获引用的方式来捕获变量 x。在 Lambda 表达式中使用的变量 x 是原有变量的引用,对其进行修改会影响原有的变量 x。 3. 捕获列表 捕获列表可以通过在捕获列表中指定变量的方式来完成。在捕获列表中,可以同时指定多个变量,并且可以使用值或引用的方式进行捕获。例如: ```c++ int x = 1, y = 2; auto func = [x, &y]() { std::cout << x << " " << y << std::endl; }; ``` 在上面的代码中,Lambda 表达式通过捕获列表的方式来捕获变量 x 和 y。变量 x 是以值的方式进行捕获的,变量 y 是以引用的方式进行捕获的。 需要注意的是,在 Lambda 表达式捕获变量时,要考虑变量的生命周期。如果捕获了一个局部变量,而且这个局部变量已经超出了作用域,那么在 Lambda 表达式执行时可能会引发未定义的行为。为了避免这种情况,可以使用捕获值或捕获引用的方式来避免变量超出作用域的问题。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值