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

时间:2013-06-05 16:15:09

标签: c++ c++11 lambda

在C ++中,您可以声明lambdas,例如:

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

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

1 个答案:

答案 0 :(得分:85)

发生了什么

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

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

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

预计会打印出来:

6
5
----
6
6

为什么

考虑lambda

可能会有所帮助
  

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

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

他们有

  

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

声明为const成员函数,但仅

  

[...]当且仅当lambda表达式的 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 ++中,指针/引用的常量不会改变通过它看到的指针/引用的常量。

相关问题