(なぜ) 移動コンストラクターまたは移動代入演算子はその引数をクリアする必要がありますか?

不要 掃除する。クラスの設計者は、移動元のオブジェクト ゼロを初期化したままにしておくことをお勧めします。

これが理にかなっている状況は、デストラクタで解放されるリソースを管理するオブジェクトの場合であることに注意してください。たとえば、動的に割り当てられたメモリへのポインタです。移動元オブジェクトのポインターを変更しないままにしておくと、2 つのオブジェクトが同じリソースを管理することになります。両方のデストラクタが解放を試みます。


クラスの作成者。

std::unique_ptr のドキュメントを見ると 、次の行の後に表示されます:

std::unique_ptr<int> pi = std::make_unique<int>(5);
auto pi2 = std::move(pi);

pi 実際には非常に定義された状態にあります。 する reset() でした と pi.get() する nullptr に等しい .


このクラスの作成者がコンストラクターに不要な操作を入れていることは、おそらく正しいでしょう。

m_wheels でも std::vector などのヒープ割り当て型 すでに 自身に渡される 移動コンストラクタ:

: m_wheels(std::move(ori.m_wheels)),   // invokes move-constructor of appropriate type

ただし、知ることを許可するのに十分なクラスを示していません。 この特定のケースで明示的な「クリア」操作が必要かどうか。 Deduplicator の回答によると、次の関数は「moved-from」状態で正しく動作することが期待されます:

// Destruction
~Motorcycle(); // This is the REALLY important one, of course
// Assignment
operator=(const Motorcycle&);
operator=(Motorcycle&&);

したがって、の実装を確認する必要があります move-constructor が正しいかどうかを判断するために、これらの関数の。

3つすべてがデフォルトの実装を使用している場合(これは、あなたが示したものから妥当と思われます)、移動元のオブジェクトを手動でクリアする理由はありません。ただし、これらの関数のいずれかが使用されている場合 m_wheels の値 、 m_speed 、または m_direction どのように動作するかを決定するために、move-constructor が必要になる場合があります 正しい動作を保証するためにそれらをクリアします。

そのようなクラス設計は、クリーンアップが発生する必要があるかどうかを示すフラグとしてプリミティブが明示的に使用されない限り、通常、「移動元」状態でプリミティブの値が重要であるとは予想されないため、洗練されておらず、エラーが発生しやすくなります。

最終的に、として C++ クラスで使用する場合、示されている移動コンストラクターは、望ましくない動作を引き起こすという意味で技術的に「間違っている」わけではありませんが、この質問を投稿する原因となった混乱を正確に引き起こす可能性があるため、悪い例のように思えます。