为什么lambda的call-operator隐式为const?

cpp*_*ast 20 c++ lambda const c++11 function-call-operator

我在下面的函数中有一个小的"lambda表达式":

int main()
{
    int x = 10;
    auto lambda = [=] () { return x + 3; };
}
Run Code Online (Sandbox Code Playgroud)

下面是为上面的lambda表达式生成的"匿名闭包类".

int main()
{
    int x = 10;

    class __lambda_3_19
    {
        public: inline /*constexpr */ int operator()() const
        {
            return x + 3;
        }

        private:
            int x;

        public: __lambda_3_19(int _x) : x{_x}
          {}

    };

    __lambda_3_19 lambda = __lambda_3_19{x};
}
Run Code Online (Sandbox Code Playgroud)

由编译器生成的闭包"operator()"是隐式const.为什么标准委员会const默认做到这一点?

P.W*_*P.W 18

Herb Sutter在open-std.org上发现了这篇论文,讨论了这个问题.

奇怪的一对:按值注入const和
quirky mutable考虑这个稻草人示例,程序员通过值捕获局部变量并尝试修改捕获的值(这是lambda对象的成员变量):

int val = 0;
auto x = [=]( item e ) // look ma, [=] means explicit copy
 { use( e, ++val ); }; // error: count is const, need ‘mutable’
auto y = [val]( item e ) // darnit, I really can’t get more explicit
 { use( e, ++val ); }; // same error: count is const, need ‘mutable’
Run Code Online (Sandbox Code Playgroud)

此功能似乎是由于用户可能没有意识到他有副本而引起的,特别是因为lambdas是可复制的,所以他可能正在更改不同的lambda副本.

以上报价和例如指示为什么标准委员会可能使人们const在默认情况下并需要mutable去改变它.


max*_*x66 9

来自cppreference

除非mutable在lambda表达式中使用了关键字,否则函数调用运算符是const限定的,并且由副本捕获的对象在此内部是不可修改的operator()

在您的情况下,通过副本捕获的任何内容都不可修改.

我想,如果你写的东西是

int x = 10;

auto lambda = [=] () mutable { x += 3; return x; };
Run Code Online (Sandbox Code Playgroud)

const应该消失

- 编辑 -

OP精确

我已经知道添加mutable会解决问题.问题是我想了解默认情况下使lambda不可变的原因.

我不是语言律师,但这似乎是显而易见的:如果你operator()没有const,你就不能做出像

template <typename F>
void foo (F const & f)
 { f(); }

// ...

foo([]{ std::cout << "lambda!" << std::endl; });
Run Code Online (Sandbox Code Playgroud)

我的意思是......如果operator()不是const,你不能使用lambdas传递它们作为const参考.

如果不严格需要,应该是一个不可接受的限制.