在同一命令中使用变量时移动到 lambda
Move to lambda while using the variable in the same command
让我们考虑以下旨在毁灭世界的结构。
#include <iostream>
#include <vector>
struct SkyNet {
std::vector<int> terminators;
SkyNet() = default;
SkyNet(SkyNet&& that)
{
printf("Move constructn");
this->terminators = std::move(that.terminators);
}
};
class Apocalypse {
public:
template <typename Lambda>
void run(Lambda lambda) {
lambda();
}
};
Apocalypse create_apocalypse(const SkyNet& net) {
std::cout << "Create: " << net.terminators.size() << " terminatorsn";
return Apocalypse();
}
(请原谅这些结构的不良设计和其他缺陷。创建它只是为了演示特定问题。
然后我们有简单的主:
int main()
{
SkyNet net;
net.terminators.push_back(10);
create_apocalypse(net)
.run([net = std::move(net)] {
std::cout << "Lambda: " << net.terminators.size() << " terminatorsn";
});
return 0;
}
其中输出:
Move construct
Create: 0 terminators
Lambda: 1 terminators
这意味着run
函数的参数将在调用链接其他事件的函数之前创建(评估?create_apocalypse
函数。正确吗?这是先计算表达式的所有参数(不仅是第一个函数的参数)然后调用函数的一般规则吗?
创建 lambda 时,您正在创建一个匿名对象。定义闭包时,将定义其构造函数和成员。
所以这相当于:
crete_apocalypse(net).run(MyLambda{std::move(net)});
这在语义上等同于类似的东西
run(create_apocalypse(net), MyLambda{std::move(net)});
由于函数参数的计算顺序未由标准指定,因此实现可以自由选择。换句话说,它可以选择先做create_apocalypse(net)
,然后按照你似乎期望的那样做,或者它可以反过来(在你的例子中是这样做的)并首先构建MyLambda
,从而移动net
,以便一旦它到达create_apocalypse()
,它就已经移动了。
当它真正重要时,你不应该依赖于你为特定编译器获得的行为。避免它并保持正确性的方法是这样写:
auto a = create_apocalypse(net);
a.run([net = std::move(net)] { /* ... */ });
演示
相关文章:
- 我应该使我的局部变量常量还是可移动的
- 为什么 std::move 不将默认移动构造函数中的源变量更改为默认值?
- 当变量和参数名称匹配时,移动语义构造失败
- 右值引用和局部变量的移动
- 是否可以通过使用移动/交换 c++11 来延长返回的临时变量的生命周期
- 是否可以将移动的变量标记为不再可用,并在使用它时收到编译器警告?
- 如何初始化非静态模板成员变量从临时工开始,即而无需复制或移动
- 从已移动捕获的 lambda 中重复移动变量
- 变量可以通过C / C 的左或右移动操作变为null
- 如何有效地将底层数据从 std::string 移动到其他类型的变量?
- 移动变量是否有效,可以在 std::move 之后使用
- C++11 是否保证 return 语句中的局部变量将被移动而不是复制?
- 如何在 c++ pytorch 前端 API 中将变量从 GPU 移动到 CPU
- 从类返回可移动成员变量
- 如何将变量移动到 lambda 表达式中
- 用向量替换类新的[]变量-移动、复制运算符
- 使用 c++ 中的 __asm 将 short 类型的变量移动到 EAX 中 (VS 2010)
- 将动态分配的变量移动到向量中
- 如何将' std::vector '成员变量移动到方法的调用方
- 将变量移动到头文件时出现运行时错误