为什么 lambda 的调用运算符隐式为 const?

Why is a lambda's call-operator implicitly const?

我在下面的函数中有一个小 "lambda expression":

int main()
{
    int x = 10;
    auto lambda = [=] () { return x + 3; };
}

下面是为上述 lambda 表达式生成的 "anonymous closure class"。

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};
}

编译器生成的闭包 "operator()" 是隐式 const。为什么标准委员会默认const

来自cppreference

Unless the keyword mutable was used in the lambda-expression, the function-call operator is const-qualified and the objects that were captured by copy are non-modifiable from inside this operator()

在你的例子中,没有任何东西,通过副本捕获,是可以修改的。

我想,如果你把东西写成

int x = 10;

auto lambda = [=] () mutable { x += 3; return x; };

const 应该消失

-- 编辑--

OP 精确

I already knew that adding mutable will solve the issue. The question is that I want to understand the reason behind making the lambda immutable by default.

我不是语言律师,但这在我看来是显而易见的:如果你让 operator() 不是 const,你就不能像

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

// ...

foo([]{ std::cout << "lambda!" << std::endl; });

我的意思是...如果 operator() 不是 const,您不能使用 lambda 将它们作为 const 引用传递。

当不是严格需要时,应该是一个不可接受的限制。

在 open-std.org 上找到了 Herb Sutter paper,其中讨论了这个问题。

The odd couple: Capture by value’s injected const and quirky mutable
Consider this strawman example, where the programmer captures a local variable by value and tries to modify the captured value (which is a member variable of the lambda object):

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’

This feature appears to have been added out of a concern that the user might not realize he got a copy, and in particular that since lambdas are copyable he might be changing a different lambda’s copy.

以上引用和示例说明了为什么标准委员会 可能 将其设为 const 并要求 mutable 对其进行更改。

我认为,这只是为了避免在 lambda 中的变量引用的不是最初捕获的内容时造成混淆。从词法上讲,这样的变量就好像在其 "original" 的范围内一样。复制主要是为了允许延长对象的生命周期。当捕获不是通过复制时,它指的是原始对象并将修改应用于原始对象,并且不会因为两个不同的对象(其中一个是隐式引入的)而混淆,并且它是 lambda 的 const 函数调用运算符所允许的。