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 ++中,指针/引用的常量不会改变通过它看到的指针/引用的常量。