1

私は c++11 マルチスレッドに関するドキュメントを読んでいて、std::thread.

コード:

void thread_task(int n) {
  ...
}

int main(int argc, const char *argv[])
{
    std::thread threads[5];
    for (int i = 0; i < 5; i++) {
        threads[i] = std::thread(thread_task, i + 1);
    }

    return 0;
}

わかりませんthreads[i] = std::thread(thread_task, i + 1);std::thread静的関数呼び出しであり、std::thread オブジェクトの参照を返しますか? 想像を絶するように聞こえますが、コードが言うことのようです。

私なら次のように書くからです。

std::thread *threads[5];
for (int i = 0; i < 5; i++) {
    threads[i] = new std::thread(thread_task, i + 1);
}

ありがとう。

4

4 に答える 4

13

何が起こっているのかを正確に見てみましょう。

std::thread threads[5];

std::threadこれにより、デフォルトで構築される 5 つのオブジェクトの配列が作成されます。現在、これらは「スレッドではない」ことを表しています。これは、デフォルトの構造がそれらを残す状態であるためです。

for (int i = 0; i < 5; i++) {
    threads[i] = std::thread(thread_task, i + 1);
}

これは の移動形式を使用しoperator=ます。スレッドはコピー可能ではなく、移動可能のみであるため、thread& operator=(thread&& t)は定義されていませんが、 は定義されてthread& operator=(const thread& t)いません。threads[i]これにより、新しく構築された にス​​レッド オブジェクトが割り当てられstd::thread(thread_task, i + 1);ます。

ここでポインターの配列を使用する理由はありません。メモリリークの可能性を追加するだけです。

于 2013-09-07T12:10:24.843 に答える
2

静的関数呼び出しであり、オブジェクトstd::threadの参照を返しますか?std::thread

いいえ、一時的なスレッド オブジェクトを作成しています。int(42)一時的な整数を作成するのと同じです。スレッドは移動可能であり、一時的なものはそこから移動できるため、割り当てはそれを配列に移動します。

私なら次のように書くからです。

正当な理由もなく、動的割り当て、余分なレベルの間接化、およびメモリ リークを導入しています (終了時にそれらを削除するコードも追加しない限り)。

于 2013-09-07T12:06:18.240 に答える
2

既定のコンストラクターは、スレッドを表さないstd::threadインスタンスを作成します。コピーも許可されていないため、割り当てはmove-assignmentです。によって作成された実際のインスタンスを配列に移動します。std::thread(thread_task, i + 1);

于 2013-09-07T12:06:47.907 に答える
2

これ:

std::thread(thread_task, i + 1)

std::thread コンストラクターへの呼び出しです。これは新しいスレッド オブジェクトを作成し、それ自体に i+1 をパラメーターとして呼び出される thread_task 関数へのポインターを渡します。

代入はコピー代入ではなく移動代入です (右側は無名オブジェクトを参照するため)。std::thread コピー コンストラクターとコピー代入演算子が削除されていることに注意してください。

これは実際にはポインターを使用するよりもクリーンな方法です。これは、std::thread オブジェクトが、threads 配列がスコープ外になると自動的に破棄されるためです。

于 2013-09-07T12:10:10.623 に答える