gpt4 book ai didi

c++ - 在同一命令中使用变量时移至 lambda

转载 作者:搜寻专家 更新时间:2023-10-31 01:36:33 24 4
gpt4 key购买 nike

让我们考虑以下旨在毁灭世界的结构。

#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();
}

(请原谅这些结构的糟糕设计和其他缺陷。创建它只是为了演示特定问题。)

然后我们有简单的主要内容:

int main()
{
SkyNet net;
net.terminators.push_back(10);

create_apocalypse(net)
.run([net = std::move(net)] {
std::cout << "Lambda: " << net.terminators.size() << " terminators\n";
});
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)] { /* ... */ });

Demo

关于c++ - 在同一命令中使用变量时移至 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35477077/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com