在lambda表达式(作为返回值)中按值捕获([x]
)(或C ++ 14移动捕获[x = std::move(x)]
)中的复制(移动)构造是否可能(或保证)被淘汰?
auto param_by_value(Widget w) {
// manipulating w ...
return [w] { w.doSomeThing(); };
}
auto param_by_move(Widget w) {
// manipulating w ...
return [w = std::move(w)] { w.doSomeThing() };
}
auto local_by_value() {
Widget w;
// manipulating w ...
return [w] { w.doSomeThing(); };
}
auto local_by_move() {
Widget w;
// manipulating w ...
return [w = std::move(w)] { w.doSomeThing() };
}
我的问题是:
w
的副本(移动)? (我记得显式std::move
有时会阻止复制省略,并且参数的复制/移动是无法消除的。)w
的按值捕获会调用Widget
的move构造函数吗?std::move
,哪个应该是最佳做法?答案 0 :(得分:4)
Lambda捕获本质上是lambda对象的成员变量。因此,它们在初始化或在lambda的operator()
重载中使用时都不受任何形式的修饰。
并且由于构造函数/析构函数的调用是可观察到的行为,因此不允许编译器在“好像”规则下调用它们(除非编译器可以看到这些构造函数/析构函数的代码,并且可以证明没有构造函数/析构函数可见的副作用。此外,它还必须遵循整个代码库中lambda的路径。因此,基本上,不要指望它。)
话虽如此,根据C ++ 17规则返回的lambda本身不会调用该lambda本身的副本/移动,因此不需要该Lambda成员的其他副本/移动。
w的按值捕获会调用Widget的move构造函数吗?
不。按值捕获总是复制。