Effective Modern C++ 第六章 lambda 表达式

lambda 能做到的,手写也能做到,但是 lambda 实在是太方便了,以至于对 C++ 开发产生了颠覆性的影响:

常用场景

  • STL _if 算法族的谓词
  • 智能指针的自定义析构器
  • 线程 API 的条件变量(对谓词进行特化处理)
  • 临时制作回调函数、接口适配函数

条款 31:避免默认捕获

  • lambda 捕获只能捕获创建 lambda 作用域内可见的局部、非静态变量(包括形参)
  • 每个非静态成员函数都持有 this 指针,成员函数中访问成员变量都是通过 this 指针
  • 成员函数中,无法捕获成员变量,成员函数中,实际上捕获的是 this 指针!
  • 【最佳实践】新建一个成员变量的副本,然后显式、值捕获该副本
  • 不能捕获静态变量!
  • 使用 lambda 时,要确保引用捕获的对象仍然有效!
  • 按值捕获的 this 指针也要保证使用 lambda 时,指针仍然有效!

无法局部静态变量的测试代码:

vector<function<void(void)>> callables;

void lambdaAddTest() {
  static int si = 0;
  // callables.emplace_back([si] { cout << si; }); // error: 'si' cannot be captured because it does not have automatic storage duration
  callables.emplace_back([=] { cout << si; }); // 警告:此处没有捕获任何变量!
  ++si;
}

int main() {
  lambdaAddTest();
  for (const auto& l : callables) {l();}
  lambdaAddTest();
  for (const auto& l : callables) {l();}
  lambdaAddTest();
  for (const auto& l : callables) {l();}
}

运行结果

122333

条款 32:使用【初始化捕获】将对象移入闭包

auto p = make_unique<Foo>();
... // 操作 p
auto func1 = [lp = move(p)] { /* 使用 lp */ };

auto func2 = [lp = make_unique<Bar>()] { /* 使用 lp */ };
posted @ 2023-02-05 10:49  Zijian/TENG  阅读(88)  评论(0编辑  收藏  举报