C++ 在C+中使用lambda默认值捕获或引用捕获的缺点+;11?
在C++11中使用lambda默认值捕获(C++ 在C+中使用lambda默认值捕获或引用捕获的缺点+;11?,c++,lambda,C++,Lambda,在C++11中使用lambda默认值捕获([=])或引用捕获([&])有哪些陷阱 我知道一些陷阱,比如: 如果从lambda创建的闭包的生存期超过了局部变量的生存期,那么闭包中的引用将挂起 默认值捕获是否有任何缺点 与以下各项相比,它具有完全相同的优点和缺点: int value(const T x) { ... } int value(T& x) { ... } 按值捕获涉及复制关闭的值,因此可能意味着该副本需要更多内存消耗和更多处理。使用[=]或[]按值捕获具有创建与捕获的实体
[=]
)或引用捕获([&]
)有哪些陷阱
我知道一些陷阱,比如:
- 如果从lambda创建的闭包的生存期超过了局部变量的生存期,那么闭包中的引用将挂起
默认值捕获是否有任何缺点 与以下各项相比,它具有完全相同的优点和缺点:
int value(const T x) { ... }
int value(T& x) { ... }
按值捕获涉及复制关闭的值,因此可能意味着该副本需要更多内存消耗和更多处理。使用
[=]
或[]
按值捕获具有创建与捕获的实体类型完全相同的lambda成员的效果,包括常数,例如。,通过值捕获常量int
时,即使lambda call运算符是可变的,也不能对结果成员进行变异
const int i = 1;
[=] () mutable { ++i; }(); // Error: increment of read-only variable.
这可以通过使用C++14初始化捕获表达式来解决:
[i = i] () mutable { ++i; }(); // Ok
我认为你提到的悬而未决的参考问题是主要的陷阱 然而,另一件有时会被忽略的事情是,即使在成员函数中使用按值捕获lambda,它也不会创建所用成员变量的副本,而只创建该指针的副本 首先,这意味着您再次面临悬空指针问题;其次,您可能会意外地修改lambda范围之外的变量,即使看起来您只是在修改本地副本 例如,这将打印
0 1 1
,而不是0 1 0
struct Foo {
int bar=0;
int bas() {
auto inc = [=]() {
bar++; //this is equivalent to this->bar++
return bar;
};
return inc();
}
};
int main() {
Foo foo;
std::cout << foo.bar <<" ";
std::cout << foo.bas() << " ";
std::cout << foo.bar << std::endl;
}
structfoo{
int bar=0;
int bas(){
汽车公司=[=](){
bar++;//这相当于->bar++
返回杆;
};
返回公司();
}
};
int main(){
富富,;
std::回答得很好,我只想补充一点,lambda是对象。因此,在按值捕获时,重复使用lambda对象将使用它的内部状态。这与使用函数如int-value(const T x){…}完全不同
。有关参考信息,请参见-@Jendas:我不确定您的参考是否正确,但您的回答是正确的,即值是在lambda创建时捕获的,而不是在调用时捕获的。嗨,比尔,谢谢您的回答,默认情况下,值类型被捕获为const,而参考类型为non-constYes。这并不能准确地解决问题,但这是最重要的t我找到了关于lambdas内部状态的信息。嗨,Mike,谢谢你的回答,根据我的理解,捕获值类型成为闭包类的数据成员,引用不会成为闭包类的数据成员。请确认。@Ajayyadav:嗯,它也会成为数据成员,但属于引用类型