2016-05-11 15 views
10

私はcommandsのパーサ(大規模なデータ配列の周りの派手なラッパー)で作業しており、未処理のコマンドが存在するキューを持っています。私は、コマンドが必要な場合は、私はこのようなコードでそれを照会:オブジェクトをキューから移動することは大丈夫ですか?

boost::optional<command> get_command() { 
    if (!has_command()) return boost::optional<command>(nullptr); 
    else { 
     boost::optional<command> comm(command_feed.front()); //command_feed is declared as a std::queue<command> 
     command_feed.pop(); 
     return comm; 
    } 
} 

問題があるが、これらのコマンドは、適切な状況の下で、サイズはメガバイトこと、そしてかなり早く解析する必要がある可能性があります。

boost::optional<command> get_command() { 
    if (!has_command()) return boost::optional<command>(nullptr); 
    else { 
     boost::optional<command> comm(std::move(command_feed.front())); //command_feed is declared as a std::queue<command> 
     command_feed.pop(); 
     return comm; 
    } 
} 

そして、この特定のケースのために働くように見えるが、これは、任意の適切に維持RAIIオブジェクトへの汎用ソリューションとして使用することができ、または:私の考えは、私はそうのような動きにtransferalを最適化するということでした私は何か他のことをしなければなりませんか?

+0

はい、そう長く**あなたがそれを行うだけ**の事はそれを –

+6

@SteveLorimerをポップか、それを再割り当てであるとして、それは安全である移動。また、前提条件なしで他の操作を行うこともできます。 –

+0

@Revolver_Ocelot割り当ては、必ずしも前提条件がないわけではありません。 –

答えて

21

はい、これは完全に安全である:

std::queue<T> q; 
// add stuff... 

T top = std::move(q.front()); 
q.pop(); 

pop()が指定された状態を有するq内の最初の要素のいずれかの前提条件を持っていない、とあなたは、その後、あなたがq.front()をしていない使用していないので、そのオブジェクトが無効になったことを処理する必要があります。

いいアイデアが好きです。

+0

'T'の特性によっては完全に安全です。安全であることは保証されていません。 – juanchopanza

+1

@juanchopanza確かに、 'T'がMoveConstructibleである限り。 – Barry

+0

それは私が念頭に置いていた必要条件です。ポイントは、*から移動した後にある状態になければならないという点です*。 – juanchopanza

4

はいstd::queueのコンテナテンプレートの引数が、pop_front()の含まれる値の状態に関する前提条件が存在しないことを保証している限り、 std::queueのデフォルトはstd::dequeであり、これは保証を提供します。

私が前の段落に書いたことを確実にする限り、あなたは完全に安全です。そのアイテムをキューから削除しようとしているので、そのオブジェクトの所有権をにしているであるため、移動しない理由はありません。

6

あなたのタイプの移動コンストラクタが何をするかによって異なります。元のオブジェクトを安全に破壊できる状態にしておくと、すべてがうまくいきます。もしそうでなければ、困っているかもしれません。前提条件と有効な状態に関するコメントは、標準ライブラリので定義された型の制約に関するものであることに注意してください。定義する型には、標準ライブラリの型を使用する場合を除いて、これらの制約はありません。だからあなたの移動コンストラクタを見て、あなたが移動可能なオブジェクトでできることとできないことを整理してください。

+4

移動元オブジェクトが破壊可能でない場合、この移動コンストラクタ/代入は基本的に使用不可能です。 –

1

オブジェクトを移動すると無効な状態になることがあります。不変量はもはや保証されません。非侵入型のキューから安全にポップすることができます。

  • std :: move自体は、r値をとる通信ルーチンを選択できるということ以外は何もしません。

  • よく書かれたcommルーチンは、新しいオブジェクトの古いオブジェクトから表現を盗みます。たとえば、ポインタを新しいオブジェクトにコピーし、古いオブジェクトのポインタをゼロにします(古いオブジェクトデストラクタは配列を破棄しません)。

  • これを行うために通信がオーバーロードされない場合、std :: movには何のメリットもありません。

+0

*オブジェクトを移動すると無効な状態になることがあります。不変量はもはや保証されません。* < - これは悪い習慣とみなされます。オブジェクトから移動すると**有効であるが不特定の**状態になります! – anderas

関連する問題