2011-10-28 15 views
14

私は2つのベクトルを持ち、1つをもう一方のベクトルに移動するとします。v1 = std::move(v2);この後でもv2は使用可能な状態になりますか?移動はオブジェクトを使用可能な状態のままにしますか?

+1

これはhttp://stackoverflow.com/q/7027523/576911の複製のようです。この回答を参照してください:http://stackoverflow.com/questions/7027523/what-c​​an-i-do-with-a-moved-from-object/7028318#7028318前提条件に関して許可された操作について議論する質問に。 –

答えて

22

、17.6.5.15を移動-からライブラリー・タイプの状態[lib.types.movedfrom] C++標準ライブラリで定義されたタイプの

  1. オブジェクト(12.8)から移動させることができます。移動操作は明示的に指定することも、暗黙的に生成することもできます。別段の指定がない限り、そのような移動オブジェクトは有効であるが不特定の状態に置かれるものとする。状態が有効であるので

が、これはあなたが安全に(例えば、既知の状態に戻ってそれを置くことになる、それに割り当てることによって)v2を操作できることを意味します。しかし、それは指定されていないので、例えば、この状態にある限り(ただし、呼び出してもプログラムをクラッシュさせることはありません)、v2.empty()の特定の値に依存することはできません。

このセマンティクス( "オブジェクトは有効であるが、指定されていない状態から移動される")のこの公理は、標準ライブラリコンポーネントだけでなく、すべてのコードが(ほとんどの場合に)努力すべきものであることに注意してください。コピーコンストラクタの意味によく似ているはコピーを作成する必要がありますが、強制はしません。

+0

+1ですが、書かれているように、 'v2 = std :: vector {};の後で' v2'が空であるかどうかわからないようです。 – Gabriel

+0

@Gabriel良い点、編集順です。 –

7

いいえ、指定されていない状態です。

open-std-org記事からの抜粋 -

...動きは()そのターゲット引数の値が得られますが、そのソースの価値を維持する義務はありません。したがって、ベクトルの場合、move()はすべての要素をコピーする必要がないように、その引数をゼロ容量のベクトルとして残すことが合理的に期待できます。つまり、移動は潜在的に破壊的な読みです。 n3290から

+7

不明な_but valid_状態のままです。つまり、オブジェクトが有効であるという前提条件だけを持つ方法でオブジェクトを使用することはできます。たとえば、移動元のベクトルに対してvector :: clear()を呼び出して、既知の状態にしてからオブジェクトを挿入することができます。 – bames53

+3

__有効である必要があります。それ以外の場合は、オブジェクトがスコープから外れるとどうなるでしょう。ほとんどの場合、データストアには何も格納されませんが、それが何であれ、有効になります。 – Damon

+1

複数の(抽象的な)妥当性のレベルがあります。言語に関する限り、移動後のオブジェクトはオブジェクトがまだ存在する限り有効であり、定義されていない動作などを引き起こすことなくデストラクタを呼び出すことができます。しかし、オブジェクトのコントラクトは移動されて変更されることがあります。例えば、ベクトルがゼロサイズ(容量を持たない)になったことは、有効なC++ベクトルですが、(現在は無効化されている)前提を検証せずにベクトル上の特定の要素を設定するメソッドを持つオブジェクトですベクトルが特定のサイズを持つ必要があります... – rwong

0

あなたはは、移動後にV2を使用したい場合は、あなたのような何かをしたいと思うでしょう。この時点で

v1 = std::move(v2); 
v2.clear(); 

を、V1はV2とv2の元の内容が十分にありますがあります定義済みの空の状態。これはすべてのSTLコンテナ(とその点については文字列)で機能し、移動セマンティクスをサポートする独自のクラスを実装する場合は、おそらく同様のことをしたいと思うでしょう。

STLの特定の実装が実際にオブジェクトを空の状態のままにしている場合、2番目のclear()は本質的にno-opになります。実際、このような場合は、コンパイラが移動後にclear()を削除することが合法的な最適化となります。

関連する問題