72

在 C++ 中,您可以像这样声明 lambdas:

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

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

4

1 回答 1

94

怎么了

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

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

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

于 2013-06-05T16:15:08.847 回答