Подтвердить что ты не робот

Можно ли определить std :: thread и инициализировать его позже?

Моя цель - сохранить объект 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);
    }
}
4b9b3361

Ответ 1

Ваша проблема - еще что-то - вы передаете экземпляр 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 удаляется). Однако функции-члены CopyThread и MoveThread требуют указателя как первого (скрытого) аргумента в любом случае.

Живая демонстрация

Ответ 2

Как обернуть его указателем?

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: И да, другие упомянули об этом, и я не ощущал необходимости добавлять его сюда, но чтобы избежать большего сложения downvote, я скажу это: вы передаете *this а не this тем самым копируя экземпляр вашего класса. (Проблемы возникают из-за того, что они не копируются. Передайте this и вам должно быть хорошо, чтобы идти.)

Ответ 3

Вы не можете инициализировать объект потока после его создания; по определению инициализация происходит, когда объект создается. Но вы можете использовать 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