是否可以定义std :: thread并在以后进行初始化?

问题描述 投票:20回答:4

我的目标是将std::thread对象保留为数据成员,并在需要时对其进行初始化。我无法执行此操作(如下面的代码所示),因为std::thread类的副本构造函数已删除。还有其他方法吗?

class MyClass
{
    public:
        MyClass():DiskJobThread(){};
        ~MyClass();

        void DoDiskJobThread();

    private:
        int CopyThread(const std::wstring & Source, const std::wstring & Target);
        int MoveThread(const std::wstring & Source, const std::wstring & Target);
        std::thread DiskJobThread;
};

MyClass::~MyClass()
{
    DiskJobThread.join();
}

void MyClass::DoDiskJobThread()
{
    std::wstring Source = GetSource();
    std::wstring Target = GetTarget();
    int m_OperationType = GetOperationType();
    if      (m_OperationType == OPERATION_COPY)
    {
        DiskJobThread = std::thread(&MyClass::CopyThread, *this, Source, Target);
    }
    else if (m_OperationType == OPERATION_MOVE)
    {
        DiskJobThread = std::thread(&MyClass::MoveThread, *this, Source, Target);
    }
}
c++ copy-constructor stdthread
4个回答
8
投票

您的问题是其他问题-您正在将MyClass的实例传递到线程中,而不是成员函数期望的MyClass指针。只需像这样更改DoDiskJobThread()(不要取消引用this):

void MyClass::DoDiskJobThread()
{
    std::wstring Source = GetSource();
    std::wstring Target = GetTarget();
    int m_OperationType = GetOperationType();
    if      (m_OperationType == OPERATION_COPY)
    {
        DiskJobThread = std::thread(&MyClass::CopyThread, this, Source, Target);
    }
    else if (m_OperationType == OPERATION_MOVE)
    {
        DiskJobThread = std::thread(&MyClass::MoveThread, this, Source, Target);
    }
}

[您收到此错误是因为*this导致试图将MyClass复制到线程函数中,并且类的复制ctor被删除(因为std::thread的复制ctor被删除)。但是,成员函数CopyThreadMoveThread无论如何都需要一个指针作为第一个(隐藏的)参数。

Live demonstration


13
投票

如何将其包装在指针中?

std::unique_ptr<std::thread> thread_ptr;

// Look into std::make_unique if possible
thread_ptr = std::unique_ptr<std::thread>(new std::thread(...));

Edit:是的,其他人都提到了它,我不认为需要在此处添加它,但是为了避免更多的下降桩,我要说:您正在通过*this而不是this从而复制您的类的实例。 (出现问题是因为它不可复制。通过this,您应该就可以了。)


9
投票

创建线程对象后,您不能初始化;根据定义,初始化是在创建对象时发生的。但是您可以使用swap将线程对象移动到另一个对象:

std::thread thr1; // no thread of execution
std::thread thr2(my_function_object); // creates thread of execution
thr1.swap(thr2);  // thr1 is now running the thread created as thr2
                  // and thr2 has no thread of execution

0
投票

我的目标是保留std::thread对象作为数据成员,并在需要时对其进行初始化。

由于默认构造的std::thread对象没有关联的执行线程,因此可以通过将此类对象用作(移动)赋值操作的目标来实现此目的。请注意,以下内容不是initialization,而是assignment

std::thread th; // no thread of execution associated with th object
// ...
th = std::thread(func);

使用std::thread创建的临时std::thread(func)对象具有关联的执行线程。通过移动分配将该执行线程的所有权转移到th –即th从临时名窃取该执行线程的所有权。

注意,如果th在分配时具有关联的执行线程,则将调用std::terminate()

© www.soinside.com 2019 - 2024. All rights reserved.