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)] { /* ... */ });