2016-05-24 7 views
3

は、ここで私が持っているものと同様のコードです。範囲ベースループ、一意のポインタ、及び移動セマンティクス

私はベクトル(1行目)を反復処理し、pointee(2行目)を使っていくつかの作業を行います。

ジョブが完了したら、結果を得て、所有権を別の場所(3行目)に渡す必要があります。

コードは問題なくコンパイルされ実行されますが、反復処理中にiterateeを移動することは合理的ではないと感じています。

公開されているC++ 11のドラフトではありますが、私はこのテーマを明確にしませんでした。

法律上のコードであるかどうか誰にでも教えてください。

+5

あなたのベクターには 'nullptr'' unique_ptr'があります。 – Jarod42

+5

あなたはベクトルイテレータを無効にしてはいけません。つまり、 'erase()' 'insert()'などを呼び出すべきです。 – Slava

+1

はい、今すぐ取得します。コメントしてくださってありがとうございます。 – AlexDenisov

答えて

5
for (auto &uptr : vector_of_unique_ptrs) 

「uptr」は、作成したすべてのタイプのunique_ptrへの参照になりました。 'uptr'はこの場合イテレータではありません。したがって、実際にはイテレータを邪魔しないので、コードは安全です。今

、あなたがこのようなコード書いていた場合:別の話だろう

for(auto iter = vec.begin(); iter != vec.end(); iter++) 

を。ループの途中でこの 'iter'でstd :: moveを使用すると問題が発生し、おそらくあなたが望むものではないでしょう。しかし、あなたのコードを使用することは、ベクトルとループに関する限り安全です。実際には、あなたのコードを見るためにいくつかの他の方法があります:

//I'm calling your vector_of_unique_ptrs 'vec' for brevity 
//and I'm assuming unique_ptr<int> just 'cause 

//This works 
for (auto iter = vec.begin(); iter != vec.end(); iter++) { 
    unique_ptr<int>& uptr = *iter; 
    auto result = do_the_job_with_pointee(uptr.get()); 
    record_intermidiate_result(result, std::move(uptr)); 
} 

//As does this 
for (size_t i = 0; i < vec.size(); i++) { 
    unique_ptr<int>& uptr = vec[i]; 
    auto result = do_the_job_with_pointee(uptr.get()); 
    record_intermidiate_result(result, std::move(uptr)); 
} 

これは、範囲ベースのforループの処理です。イテレータを使用し、それを逆参照するので、イテレータに実際に触れることはありません。

+1

このような詳細な回答をありがとうございます。今、私の頭の中の絵ははっきりしています。 – AlexDenisov

10

あなたのコードは、正当な正当な使用権を有しており、正式なものです。反復中にシーケンスの要素を変更することはできません。移動は単なる変更の一形態です。

ループの後にこれらのポインタを使用しないようにしてください。

関連する問題