gpt4 book ai didi

c++ - 将 std::move 与 lambda 一起使用时,移动何时发生

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:03:11 34 4
gpt4 key购买 nike

如果我在函数中创建一个 lambda 并使用 std::move 将变量捕获到 lambda,那么移动何时发生?是在创建 lambda 时还是在执行 lambda 时?

以下面的代码为例……各种走法是什么时候发生的?如果在一个线程上调用 myFunction 而在另一个线程上执行 testLambda 是否线程安全?

class MyClass {
private:
// Only accessed on thread B
std::vector<int> myStuff;

// Called from thread A with new data
void myFunction(const std::vector<int>&& theirStuff) {

// Stored to be called on thread B
auto testLambda = [this, _theirStuff{ std::move(theirStuff) }]() {
myStuff = std::move(_theirStuff);
};

// ... store lambda
}

// Elsewhere on thread A
void someOtherFunction() {
std::vector<int> newStuff = { 1, 2, .... n };
gGlobalMyClass->myFunction(std::move(newStuff));
}

最佳答案

If I create a lambda in a function and capture a variable to the lambda using std::move, when does the move happen? Is it when the lambda is created or when the lambda is executed?

如果您写的是我认为您打算写的内容,那么答案将是:两者兼而有之。目前,答案是:两者都不是。你有一个 lambda 捕获 _theirStuff { std::move(theirStuff) } .这基本上声明了一个闭包类型的成员,它将在创建闭包对象时被初始化,就好像它是

auto _theirStuff { std::move(theirStuff) };

你还有

myStuff = std::move(_theirStuff);

在 lambda 主体中。

但是,您的参数theirStuff实际上是对 const std::vector<int> 的右值引用.因此,_theirStuff { std::move(theirStuff) }实际上不会执行移动,因为 const std::vector无法移动。很可能,您想写 std::vector<int>&& theirStuff反而。此外,正如@JVApen 在下面的评论中指出的那样,您的 lambda 是不可变的。因此,_theirStuff实际上也将是 const,因此也不能从中移动。因此,你上面的代码,尽管所有 std::move , 实际上每次都会复制 vector 。如果你写了

void myFunction(std::vector<int>&& theirStuff)
{
auto testLambda = [this, _theirStuff { std::move(theirStuff) }]() {
myStuff = std::move(_theirStuff);
};
}

你会移动 theirStuff进入_theirStuff当创建闭包对象时。你会复制 _theirStuff进入myStuff当调用 lambda 时。如果你写了

void myFunction(std::vector<int>&& theirStuff)
{
auto testLambda = [this, _theirStuff { std::move(theirStuff) }]() mutable {
myStuff = std::move(_theirStuff);
};
}

然后你会移动theirStuff进入_theirStuff当创建闭包对象时。你会移动_theirStuff进入myStuff当调用 lambda 时。请注意,因此,您的 lambda 不能真正被调用两次。我的意思是,它可以,但自_theirStuff 以来它只会真正起作用一次。将在第一次调用 lambda 后为空......

另请注意,以上描述仅对示例中的特定类型组合有效。对于移动对象的实际含义没有一般定义。移动对象的含义完全取决于对象的特定类型。它甚至可能没有任何意义。 std::move本身并没有真正做任何事情。它所做的只是将给定的表达式转换为右值引用。如果您随后根据 std::move 的结果初始化另一个对象, 或将结果分配给一个对象,重载决策将选择一个移动构造函数或移动赋值运算符(如果存在的话),而不是普通的复制构造函数或复制赋值运算符。然后由相应类型的移动构造函数/移动赋值运算符的实现来实际执行移动,即,在从右值初始化或赋值的情况下,为特定类型做任何应该做的事情。所以,在某种程度上,当你申请 std::move 时你做了什么是您将相应的对象宣传为“这可能会被移走”。它是否真的会被移除(如果是,那实际意味着什么)取决于实现。在 std::vector 的特殊情况下, move constructor/move assignment operator,顾名思义,保证不仅原始vector的内容会被原始对象接管,而且之后原始对象为空。在许多其他情况下,对从中移出的对象执行任何操作可能是未定义的行为(除了,也许,销毁它;一个可以被视为理所当然的类型,至少不允许这样做几乎没用;通常,您至少可以为从中移出的对象分配一个新值,但通常也不能保证)。您总是必须检查手头的特定类型,对象在从......移出后保证处于什么条件

关于c++ - 将 std::move 与 lambda 一起使用时,移动何时发生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55776047/

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