5

クラスが常に内部変数を初期化する必要があるため、クラスにデフォルトのコンストラクターがない場合、移動コンストラクターを持つべきではないということになりますか?

class Example final {
public:
  explicit Example(const std::string& string) : string_(
    string.empty() ? throw std::invalid_argument("string is empty") : string) {}
  Example(const Example& other) : string_(other.string_) {}
private:
  Example() = delete;
  Example(Example&& other) = delete;
  Example& operator=(const Example& rhs) = delete;
  Example& operator=(Example&& rhs) = delete;
  const std::string string_;
};

このクラスは常に、内部文字列が空でない文字列によって設定されることを想定しており、内部文字列はExampleオブジェクト間でコピーされます。Example が移動された場合、std::move呼び出しを介して文字列を空のままにしておく必要があるため、移動コンストラクターはここでは適用されません。

4

1 に答える 1

6

クラスが常に内部変数を初期化する必要があるため、クラスにデフォルトのコンストラクターがない場合、移動コンストラクターを持つべきではないということになりますか?

いいえ、そうは思いません

オブジェクトから移動しExampleて空の文字列のままにしておくという事実は、ここでは問題になりません。通常、クライアントは、移動元のオブジェクトが正当であるという事実を除けば、その状態について何の仮定もすべきではないからです。

つまり、クライアントは、Example入力の状態に事前条件がない関数のみを呼び出すことができます。通常、のほとんどすべてのメンバー関数はExample、オブジェクトの状態に関する前提条件 (つまりstring_、null 以外の文字列でなければならない) を持っていますが、正確にすべてではないことに注意してください。

たとえば、 のデストラクタはExampleifstring_が空であっても気にしないでください。代入演算子はもう 1 つの一般的な例です。新しい文字列を ? に代入できないのはなぜstring_ですか。

このビューでは、Exampleオブジェクトを空の文字列のままにしておくことは問題ありません。これは、クライアントが移動元オブジェクトに対してできることは、基本的に再割り当てまたは破棄のいずれかであるためです。これらのユースケースでは、string_空かどうかは問題ではありません.

したがって、ムーブ コンストラクターとムーブ代入演算子を使用することは理にかなっています。

于 2013-04-15T16:05:59.293 に答える