C ++ Lambdas:“可变”和“引用捕获”之间的区别

在C ++中,你可以像这样声明lambdaexpression式:

int x = 5; auto a = [=]() mutable { ++x; std::cout << x << '\n'; }; auto b = [&]() { ++x; std::cout << x << '\n'; }; 

都让我修改x ,那有什么区别?

发生什么事

第一个将只修改它自己的x副本,并保持外部x不变。 第二个会修改外面的x

尝试每个后添加一个打印语句:

 a(); std::cout << x << "----\n"; b(); std::cout << x << '\n'; 

这是预计打印:

 6 5 ---- 6 6 

为什么

这可能有助于考虑lambda [...] expressions provide a concise way to create simple function objects (请参阅标准的[expr.prim.lambda])。

它们有一个公共的内联函数调用操作符 ,它被声明为一个const成员函数,但是当且仅当lambdaexpression式的parameter-declaration-clause之后没有mutable (斜体文字=来自标准的引号)。

你可以想像

  int x = 5; auto a = [=]() mutable { ++x; std::cout << x << '\n'; }; ==> int x = 5; class __lambda_a { int x; public: __lambda_a () : x($lookup-one-outer$::x) {} inline void operator() { ++x; std::cout << x << '\n'; } } a; 

  auto b = [&]() { ++x; std::cout << x << '\n'; }; ==> int x = 5; class __lambda_b { int &x; public: __lambda_b() : x($lookup-one-outer$::x) {} inline void operator() const { ++x; std::cout << x << '\n'; } // ^^^^^ } b; 

问:但如果它是一个const函数,为什么我仍然可以改变x

– 答:你只是改变外面的x lambda自己的x是一个引用,操作++x不会修改引用 ,而是引用 的值

这是有效的,因为在C ++中,指针/引用的常量不会改变通过它看到的指针/引用的常量。