2017-06-13 5 views
2

次のコードが安全に使用できるかどうか、もしそうでない場合は安全にすることができますか?移動して参照を追跡しますか?

{ 
    ThreadState state = ThreadState::Running; 
    auto pair = std::make_pair(std::async([&state]() 
    { 
     state = ThreadState::Waiting; 
    }), std::move(state)); 
    someVector.emplace(std::move(pair)); 
} 

ラムダはstd::moveを実行した後、適切な参照を追跡するのでしょうか?国家の生涯は延長されるのだろうか?これを改善してラムダとその捕捉状態のペアを作成できますか?

+0

は、これらの列挙型はありますか?あなたは何をしようとしているのですか?おそらくもっと良い方法がありますか? – Nim

+0

@ニム私がやっていることの最小の例です。より良い方法がありますか? https://pastebin.com/embed_js/9DKguWeK –

+0

これは正しいとは言えません。たとえば、テストに来たときに内部ループで完了した非同期タスクがない場合は、外部ループが再び実行され、タスク - 理論的には、必要なバッチサイズよりも多くのタスクを持つことができます。タスクを開始する内部ループの下に、それらのすべてが完了するのを待つ必要があります。これにより、多くてもスレッド数必要です.. – Nim

答えて

2

std :: moveを実行した後でラムダが適切な参照を追跡しますか?

いいえ、ラムダは移動したものを参照します。stateは不定値になります。

状態の有効期間は延長されますか?

stateの有効期間は、囲みスコープの終了時に終了します。 stateの値を移動するstd::pair内の状態の存続期間は、当然std::vectorの寿命によって決定されます。

これを改善して、ラムダとキャプチャされた状態のペアを作成できますか?

一つの解決策、それは動的なストレージを使用するが、std::unique_ptrを使用することです:

{ 
    auto state = std::make_unique<ThreadState>(ThreadState::Running); 
    vec.emplace_back(
    std::async([s = state.get()]() 
    { 
     *s = ThreadState::Waiting; 
    }), 
    std::move(state) 
); 
} 
+0

私は最初に空のラムダでペアを作成し、ラムダをペアの第2要素からキャプチャするために交換する必要がありますか? –

+1

@AdamHunyadi: 'std :: vector'を' std :: vector'に移動/コピーするとき(またはそのベクトルのサイズが変更されたとき)、 'ThreadState'も動くので、おそらく動作しません。参照。 – You

+1

@あなたはラムダだけを更新すれば、これはうまくいくはずです。 'vec.back()。first = [state =&vec.back()。second](){}'ですが、ベクトルのサイズを変更するなどしても保持されませんが、これは、OPがやりたいことです。 – Holt

関連する問題