web-dev-qa-db-ja.com

移動したコンテナを再利用しますか?

移動したコンテナを再利用する正しい方法は何ですか?

std::vector<int> container;
container.Push_back(1);
auto container2 = std::move(container);

// ver1: Do nothing
//container2.clear(); // ver2: "Reset"
container = std::vector<int>() // ver3: Reinitialize

container.Push_back(2);
assert(container.size() == 1 && container.front() == 2);

私がC++ 0x標準ドラフトで読んだことから。 ver3は正しい方法のようです。移動後のオブジェクトは

「特に指定されていない限り、そのような移動元のオブジェクトは、有効であるが指定されていない状態に置かれます。」

「それ以外の場合」が指定されているインスタンスを見つけたことはありません。

Ver3は少しラウンドアバウトであり、ver1がはるかに優先されますが、vec3は追加の最適化を許可できますが、一方で間違いを簡単に引き起こす可能性があります。

私の仮定は正しいですか?

80
ronag

仕様「有効だが未指定の状態」のセクション17.3.26から:

オブジェクトの不変条件が満たされ、オブジェクトに対する操作がそのタイプに対して指定されたとおりに動作することを除いて、指定されていないオブジェクトの状態[例:タイプ_std::vector<int>_のオブジェクトxが有効であるが指定されていない場合状態、x.empty()は無条件で呼び出すことができ、x.front()x.empty()がfalseを返す場合にのみ呼び出すことができます。 —例を終了]

したがって、オブジェクトはライブです。前提条件を必要としない操作を実行できます(最初に前提条件を確認しない限り)。

たとえば、clearには前提条件がありません。そして、オブジェクトを既知の状態に戻します。だから、それをクリアして通常通りに使用してください。

91
Nicol Bolas

オブジェクトが有効だが未定義の状態であるということは、基本的にオブジェクトの正確な状態は保証されないが有効であり、そのようなメンバー関数(または非メンバー関数)が次のように動作することが保証されていることを意味しますそれらが特定の状態を持つオブジェクトに依存しない限り。

clear()メンバー関数には、オブジェクトの状態に関する前提条件がないため(もちろん、それが有効であることを除き)、移動元のオブジェクトで呼び出すことができます。一方、たとえばfront()は空でないコンテナに依存しているため、空でないことが保証されていないため、呼び出すことができません。

したがって、ver2とver3はどちらも問題ありません。

10
Grizzly