1.104、C++ 的闭包

闭包(Closure)在C++中指的是带有状态的函数对象,即一个函数加上它所捕获的外部变量状态,形成一个可调用且携带上下文信息的实体。它本质上是一个类对象,重载了operator(),能够像函数一样被调用,同时保存了调用环境中的变量。


1. 闭包的核心概念

  • • 状态(上下文):闭包捕获并持有定义时作用域中的变量(通过值或引用),使得函数调用时能够访问这些变量。
  • • 函数对象:闭包是一个匿名的、重载了operator()的类实例,兼具数据和行为。
  • • 带状态的函数:区别于普通函数,闭包“带上了状态”,即封装了外部变量。

2. C++中闭包的实现方式

  • • 手写函数对象(仿函数):定义一个类,成员变量保存状态,重载operator()实现调用。
  • • std::bind绑定器:通过绑定函数和参数,生成带状态的函数对象。
  • • Lambda表达式(C++11起):语法糖,自动生成匿名闭包类,捕获外部变量,简洁高效。

3. Lambda表达式与闭包

Lambda表达式是创建闭包的最常用方式,其语法结构如下:

[capture_list](parameters) -> return_type { function_body }
  • • 捕获列表(capture_list):指定捕获外部变量的方式(按值[=]或按引用[&])。
  • • 参数列表:函数参数。
  • • 返回类型(可选):指定返回值类型。
  • • 函数体:具体实现。

示例:

int x = 10;
auto closure = [x](int y) { return x + y; };  // 捕获x的副本
int result = closure(5);  // result == 15

4. 捕获方式的区别

  • • 按值捕获([=]):闭包内部保存变量的副本,外部变量修改不影响闭包中值,闭包内变量默认不可修改(除非用mutable)。
  • • 按引用捕获([&]):闭包内部保存变量的引用,外部变量修改会影响闭包,闭包内也可修改外部变量。

5. 闭包的应用场景

  • • 作为回调函数或事件处理函数,携带状态。
  • • 传递给STL算法(如std::sortstd::find_if)实现定制逻辑。
  • • 异步编程和并行计算中,封装执行上下文。
  • • 替代传统函数对象,简化代码,提高可读性。

6. 本质与底层实现

  • • 编译器将Lambda表达式转换为一个匿名类,捕获的变量作为成员变量,operator()实现函数体。
  • • 该匿名类实例即为闭包对象。
  • • 通过autostd::function变量保存闭包。

总结

C++闭包是带有捕获状态的函数对象,通过捕获外部变量,实现函数与状态的绑定。Lambda表达式是创建闭包的现代语法糖,简洁且高效。闭包广泛应用于函数式编程风格、STL算法和异步编程中,是现代C++不可或缺的编程工具。
(加入我的知识星球,免费获取账号,解锁所有文章。)
本文首发于【讳疾忌医-note】公众号,未经授权,不得转载。

阅读剩余
THE END