web-dev-qa-db-ja.com

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);
    }
}
18
hkBattousai

問題は別のものです。メンバー関数が期待する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);
    }
}

*thisMyClassをスレッド関数にコピーしようとしたためにエラーが発生し、クラスのコピーctorが削除されました(std::threadのコピーctorが削除されたため)。ただし、メンバー関数CopyThreadおよびMoveThreadには、とにかく最初の(非表示の)引数としてポインターが必要です。

ライブデモンストレーション

6
Angew

ポインタでラップするのはどうですか?

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

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

編集:はい、他の人がそれについて言及していて、ここに追加する必要性を感じませんでしたが、より多くの反対意見の積み重ねを避けるために、私はそれを言います:あなたは*thisthisではなく、それによってクラスのインスタンスをコピーします。 (コピーできないため、問題が発生します。thisを渡すと、問題が発生するはずです。)

11

作成後にスレッドオブジェクトを初期化することはできません。定義上、初期化はオブジェクトの作成時に発生します。ただし、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
8
Pete Becker