Lambda 按值捕获和“可变”关键字
Posted
技术标签:
【中文标题】Lambda 按值捕获和“可变”关键字【英文标题】:Lambda capture by value and the "mutable" keyword 【发布时间】:2017-06-22 17:25:23 【问题描述】:在 lambdas 中需要关键字 mutable
,这是非常混乱的根源。
考虑代码:
int x = 10;
function<void()> lambda = [=]() mutable x++; cout << "Inside lambda: x = " << x << "\n";;
cout << "Before lambda: x = " << x << "\n";
lambda();
cout << "After lambda: x = " << x << "\n\n";
输出:
Before lambda: x = 10
Inside lambda: x = 11
After lambda: x = 10
正如我们所见,变量 x
在 lambda 之后保持不变,因此没有副作用。
但是,如果我们“忘记”关键字 mutable,就会出现错误。
作为在 C++ 中按值传递默认值的参数,对我来说需要 mutable 关键字没有任何意义。
有人可以编写(即使是伪代码)编译器生成的类来代替 lambda 吗?
谢谢
【问题讨论】:
C++0x lambda capture by value always const?的可能重复 【参考方案1】:如 here 所述,mutable
说明符允许 lambda 修改由复制捕获的参数并调用它们的非常量成员函数。它不会影响通过引用捕获的变量。
有人可以编写(即使是伪代码)编译器生成的类来代替 lambda 吗?
给出一般情况并不容易,但我们可以定义一些对您的具体情况有效的内容。 生成的类可能如下所示:
struct Lambda
void operator()() x++;
int x10;
;
如果删除mutable
说明符,则函数运算符定义为const
:
struct Lambda
void operator()() const x++;
int x10;
;
为简单起见,我已使用给定值 (10) 初始化 x
并将其公开,但它显然是通过使用从周围上下文捕获的变量复制初始化的,并且无法从函数运算符外部访问。
它的类型也是从用于初始化它的变量中推断出来的,就像你这样做一样:
auto lambda_x = x;
更多详情请参阅here。
【讨论】:
【参考方案2】:class Lambda
public:
Lambda(const Lambda&);
~Lambda();
// the main functor operator, const when lambda not mutable
R operator()(Args args) const;
// Only present for non-capture lambda
operator PlainCFunctionType () const;
// Only present for non-capture lambda
PlainCFunctionType operator+() const;
private:
// Gets called when lambda created, but you can't call it yourself
Lambda(Captures captures...);
Captures captures;
;
【讨论】:
【参考方案3】:您并没有真正以面向对象的方式编写代码,但无论如何。 通常由 [=] 添加的外部变量是 const 值。通过添加 mutable 关键字,您可以创建它们的本地可修改副本。 您可以使用 [&] 来通过引用进行捕获。
【讨论】:
使用 [&] 改变 lambda 后的变量值。在我的代码中,捕获是按值进行的。以上是关于Lambda 按值捕获和“可变”关键字的主要内容,如果未能解决你的问题,请参考以下文章