是否可以定义一个std :: thread并在以后初始化它?

时间:2013-08-22 09:06:38

标签: c++ copy-constructor stdthread

我的目标是将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);
    }
}

4 个答案:

答案 0 :(得分:11)

如何将它包装在指针中?

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

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

编辑:是的,其他人已经提到了它,我觉得不需要在这里添加它,但为了避免更多的downvote打桩,我会说:你是传递*this而不是this,从而复制您班级的实例。 (问题出现是因为它是不可复制的。通过this你应该好好去。)

答案 1 :(得分:7)

创建后,您无法初始化线程对象;根据定义,在创建对象时进行初始化。但您可以使用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

答案 2 :(得分:4)

您的问题是另一回事 - 您将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复制到线程函数中,并且删除了类的复制文件(因为删除了std::thread的复制文件) 。但是,成员函数CopyThreadMoveThread无论如何都需要指针作为第一个(隐藏)参数。

<强> Live demonstration

答案 3 :(得分:1)

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

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

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()将被调用。