在C++11中使用lambda默认值捕获或引用捕获的缺点
Disadvantage of using lambda default capture by value or reference in C++11?
在C++11中使用lambda默认值捕获([=]
)或引用捕获([&]
)有哪些陷阱?
我知道一些陷阱,比如:
- 如果从lambda创建的闭包的生存期超过了局部变量的生存期,那么闭包中的引用将悬空
默认值捕获有什么缺点吗?
我认为您提到的悬挂引用问题是主要的陷阱。
然而,另一件有时被忽视的事情是,即使在成员函数中使用按值捕获lambda,它也不会创建所用成员变量的副本,而只创建this
指针的副本。
首先,这意味着您再次对悬挂指针问题持开放态度;其次,您可能会意外地修改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;
}
编辑:只是为了避免与@Snps:
提出的观点有关的混淆如果bar
是bas()
中的局部变量(因此由值捕获),则上述lambda不会编译,因为默认情况下,由值捕获的变量是const,除非显式指定lambda为可变。所以,仔细想想,很明显,bar并没有被复制,但在阅读或编写代码时,它很容易被遗忘。
它与之间的比较具有完全相同的优点和缺点
int value(const T x) { ... }
int value(T& x) { ... }
使用[=]
或[<identifier>]
按值捕获具有创建与捕获的实体类型完全相同的lambda成员的效果,包括constness,例如。当按值捕获const int
时,即使lambda调用运算符是可变的,结果成员也可以不发生突变。
const int i = 1;
[=] () mutable { ++i; }(); // Error: increment of read-only variable.
这可以通过使用C++14的初始化捕获表达式来解决:
[i = i] () mutable { ++i; }(); // Ok
按值捕获涉及复制关闭的值,因此可能意味着更多的内存消耗和对该副本的更多处理。
相关文章:
- 将对象数组的引用传递给函数
- 什么时候在C++中返回常量引用是个好主意
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 何时在引用或唯一指针上使用移动语义
- 如何在c++中使用引用实现类似python的行为
- 编译C++时未定义的引用
- Ctypes wstring通过引用传递
- c++r值引用应用于函数指针
- 理解c++中的引用
- C++取消引用指针.为什么会发生变化
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 将字段(在类中)定义为引用的缺点是什么?
- 优点和缺点..作为值或引用的常量
- 在C++11中使用lambda默认值捕获或引用捕获的缺点
- 作为类成员持有对外部对象的引用的优点/缺点
- 使用引用代替指针有哪些缺点?
- 在无锁的pop()中使用引用参数返回值的缺点
- 问题处理缺点引用另一个类中的类