29

規格によると、

クラス X の定義でムーブ コンストラクターが明示的に宣言されていない場合、1 つが暗黙的にデフォルトとして宣言されます。

— X にはユーザー宣言のコピー コンストラクターがありません。

— X には、ユーザー宣言のコピー代入演算子がありません。

— X にはユーザー宣言の移動代入演算子がなく、かつ

— X にはユーザー宣言のデストラクタがありません。

現在、以下はコンパイルに失敗します

# include <utility>

class Foo
{
public:
  Foo() = default;
  Foo(Foo const &) = delete;
};

int main()
{
  Foo f;
  Foo g(std::move(f)); // compilation fails here
  return 0;
}

したがって、削除された関数はユーザー定義と見なされるようです。これは理にかなっています (デフォルトの実装ではありません)。ただし、その特定のケースでは、削除されたコピー コンストラクター/代入の混乱はどのようにデフォルトの移動コンストラクター/代入になるでしょうか?

手動生成と esp. このようなデフォルト関数のメンテナンスはエラーが発生しやすいと同時に、std::unique_ptrクラス メンバーなどのクラスの使用が (正当に) 増加したことで、コピー不可能なクラスが以前よりもはるかに一般的な獣になりました。

4

3 に答える 3

-1

動作は基本的に次のように説明できます。

void foo(const int& i)
{
    std::cout << "copy";
}

void foo(int&& i)
{
    std::cout << "move";
}

両方のオーバーロードが存在する場合、int&&右辺const int&値に対してオーバーロードが選択され、左辺値に対してオーバーロードが選択されます。int&&オーバーロードを削除するconst int&と、右辺値に対しても (エラーではなく) が呼び出されます。これは本質的に、この場合に起こっていることです:

class Foo
{
public:
  Foo() = default;
  Foo(Foo const &) = delete;
};

オーバーロードの解決では候補が 1 つしか表示されませんが、明示的に削除されるため、プログラムの形式が正しくありません。

あなたが引用したセクションの下の非規範的なメモは、これが起こっていることを明確にしています:

[ 注:ムーブ コンストラクターが暗黙的に宣言されていないか、明示的に提供されていない場合、そうでなければムーブ コンストラクターを呼び出す式は、代わりにコピー コンストラクターを呼び出すことができます。—終了注記]

于 2016-05-17T13:11:16.857 に答える