gpt4 book ai didi

c++ - 为什么不可能将变量 move 到另一个 std::thread

转载 作者:可可西里 更新时间:2023-11-01 13:27:48 25 4
gpt4 key购买 nike

不能将一个对象 move 到另一个std::thread 的原因是什么?在某些情况下它可能会有用。例如:

您创建了一个接受传入套接字连接的循环。将传入连接 move 到另一个将处理连接的线程会很好。您不再需要接受循环中的连接。那么为什么要创建一个指针呢?

一个小测试用例:

#include <iostream>
#include <thread>

using namespace std;

class Pointertest
{
public:
Pointertest() {cout << "Constructor";}
Pointertest(Pointertest &pointertest) {cout << "Copy";}
Pointertest(Pointertest &&pointertest) {cout << "Move";}
~Pointertest() {cout << "Destruct";}
};

void foo(Pointertest &&pointertest)
{

}

int main()
{
Pointertest pointertest;

foo(std::move(pointertest)); //Works
thread test(foo,std::move(pointertest)); //**cannot convert parameter 1 from 'Pointertest' to 'Pointertest &&'**
}

最佳答案

std::thread构造函数必须以与大多数转发函数有所不同的方式处理您提供的参数。

之所以会这样,是因为线程真正开始的时间问题。如果实际创建函数参数的函数调用部分在 thread 之后运行很长时间对象被创建(这是完全合法的行为),那么需要 move 的对象可能早就被销毁了。

只需考虑您的代码的更改版本:

std::thread some_func()
{
Pointertest pointertest;

thread test(foo,std::move(pointertest));
return test;
}

这是完全有效的(线程将被移出函数)。但是,有一个大问题。 foo可能还没有被调用。自 foo通过引用获取其参数,它现在具有对已被销毁的堆栈变量的引用。

这很糟糕。但即使 foo按值获取它的参数,它不会改变任何东西。因为直到线程启动后某个不确定的时间才会实际 move 到该参数。尝试移入参数仍将使用对已销毁的堆栈变量的右值引用。这又很糟糕。

因此,std::thread构造函数做了一些不同的事情。它将您提供给它的参数复制/move 到内部存储中(这是在当前线程上完成的)。然后它将这些值用作实际函数调用的参数(这是在新线程上完成的)。

根据标准,线程构造函数应该将这些内部变量作为临时变量 传递给您的函数。该标准明确指出INVOKE (DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) , 其中DECAY_COPY事情发生在原始线程上,而 INVOKE部分发生在新线程上。

所以它看起来像你的 thread实现无法正确转发不可复制的参数。您应该能够传递不可复制的类型;参数只需要是 MoveConstructible .

所以这似乎是您实现中的一个错误。

关于c++ - 为什么不可能将变量 move 到另一个 std::thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16528048/

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