【发布时间】:2017-10-20 03:45:12
【问题描述】:
我正在检查一些我用 lambda 尝试过的旧代码,我注意到了。 如果我将 lambda 捕获指定为副本并修改其中的值,它将修改变量,因为它是一个引用。
void classV::setLambda() {
r.setLambda([=]() {
value = 100;
v = 10;
std::cout << &value << std::endl;
});
}
void classV::executeLambda() {
r.runLambda();
std::cout << "NVAL: " << value << std::endl;
std::cout << "NVAL: " << v << std::endl;
std::cout << &value << std::endl;
}
基本上,这段代码在外部对象(类实例)上存储一个 lambda 并在那里执行,我想象,当我试图获取那些不应该改变的变量的值时,将捕获指定为副本。 .. 因为它被复制了。
但是,事实并非如此,value 和 v 都是 100 和 10。 具体来说,value是classV的静态int,v是classV的int对象属性。
为什么要更改这些值?,我检查了 lambda 和 executeLambda 中的地址,它们是相同的,难道只有通过引用捕获它才会发生吗?可能我在这里遗漏了一些东西。
【问题讨论】:
-
根据cppreference,“[=] 捕获通过复制和当前的lambda主体中使用的所有自动变量引用对象如果存在”。
-
我不太确定 cppreference 在技术上是否正确,或者在技术上
this指针是否被复制捕获,但无论哪种方式,它都不应该复制您的实例变量或静态变量。 -
一个 lambda 可以捕获局部变量(按值或按引用)和/或
this(总是按值,但它没有任何区别,因为无论如何都不能分配this) .在[=, &i]的示例中,i实际上是一个局部变量(一个函数参数)。在您的示例中,v和value不是局部变量;它们要么是classV的成员(通过捕获的this访问),要么是全局变量(您没有显示足够的代码来确定哪个)。 -
这个问题很有意思,能不能发个完整的运行代码让我们试试?
-
您似乎在询问有关您未显示的代码的问题。在您显示的代码中,没有名称冲突(有未声明的标识符,但没有多次声明的标识符)。如果您需要有关特定场景的帮助,请显示演示该场景的代码。