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

在 C + + 中,你可以像下面这样声明 lambdas:

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

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

9998 次浏览

发生了什么

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

每次尝试后添加一个 print 语句:

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

这份报告预计将印刷:

6
5
----
6
6

为什么

考虑一下那个 Lambda 可能会有帮助

[ ... ]表达式提供了创建简单函数对象的简明方法

(见标准[ expr.prim.lambda ])

是的

[ ... ]公共内联函数调用运算符[ ... ]

它被声明为 const成员函数,但只能

[ ... ]当且仅当 lambda 表达式的 参数-声明-子句后面没有跟着 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

A: 你只是改变了 外部 x。Lambda 自己的 x是一个引用,操作 ++x不修改 参考文献,而是修改 参考值

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