C++ 在同一命令中使用变量时移动到lambda 让我们考虑以下结构来破坏世界。
C++ 在同一命令中使用变量时移动到lambda 让我们考虑以下结构来破坏世界。,c++,lambda,c++14,operator-precedence,C++,Lambda,C++14,Operator Precedence,#include <iostream> #include <vector> struct SkyNet { std::vector<int> terminators; SkyNet() = default; SkyNet(SkyNet&& that) { printf("Move construct\n"); this->terminators = std::move(t
#include <iostream>
#include <vector>
struct SkyNet {
std::vector<int> terminators;
SkyNet() = default;
SkyNet(SkyNet&& that)
{
printf("Move construct\n");
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() << " terminators\n";
return Apocalypse();
}
这意味着在调用
create\u apocalypse
函数之前,将创建run
函数的参数(计算?),其他事件将链接到该函数。对吗?表达式的所有参数(不仅仅是第一个函数的参数)都首先求值,然后才调用函数,这是一条一般规则吗?当您创建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)] { /* ... */ });
顺序未指定,例如
f(foo(),bar())
。我明白了。你知道这其中的原因吗?它可能允许使用最佳顺序进行优化。
run(create_apocalypse(net), MyLambda{std::move(net)});
auto a = create_apocalypse(net);
a.run([net = std::move(net)] { /* ... */ });