为什么'可变'是一个lambda函数属性,而不是一个捕获types?
为什么c ++ 11要求我们写:
[a,b]() mutable { a=7; } // b is needlessly mutable, potential source of bugs
代替:
[mutable a,b]() { a=7; } // no problems here
这是一个疏忽,认为不够重要,还是有特定的技术原因?
关于你在n2651的build议有一个提到:
lambdaexpression式的语法可以扩展为允许声明闭包成员是否应声明为mutable。
这种方法可能会让程序员感到困惑,因为可变性不是闭包对象的属性,而是存储在闭包中的variables。
我不知道这是否是唯一的原因,但似乎是这样。 但是,在Herb Sutter的提议中 ,他build议摆脱可mutable
而不是使捕获副本隐含地为const
,所以我们可能会再次看到变化。
可能是一种监督(就像不能使用右值参考一样),这是一种lambdas在概念上被实现的方式。
int a; int* b; float c; auto lambda1 = [&a, b, c](int d) mutable -> void {}; class lambda1 { public: void operator()(int d) {} private: int& a_; int* b_; float c_; }; auto lambda2 = [&a, b, c](int d) -> void {}; class lambda2 { public: void operator()(int d) const {} private: int& a_; int* b_; float c_; };
mutable
关键字适用于由lambdaexpression式生成的对象,而不是单独捕获的项目,以便它可以由编译器在operator()
方法上使用const
修饰符来实现,如标准的第5.1.2节第5段。
这个函数调用操作符被声明为const(9.3.1)当且仅当lambdaexpression式的参数声明子句没有跟随可变。
在您的示例中,由lambdaexpression式生成的类可能如下所示:
class lambda { int a, b; public: lambda( int a, int b ) : a( a ), b( b ) {} void operator()() // non-const due to mutable keyword { a = 7; } };
mutable
关键字不像通常使用的mutable
关键字那样使用:在这种情况下,它的意思是与const
相反,并且适用于函数调用操作符的隐式函数对象的const
。 但是,默认情况下隐式函数对象的函数调用操作符是const
,而通常成员函数是非常量(“可变”),但是是默认的。 lambda函数的引入早于上下文关键字( override
和final
)的使用,而mutable
关键字似乎是比not const
更好的select。