web-dev-qa-db-ja.com

デフォルトのクラスコンストラクターを削除する意味は何ですか?

私はCPP試験の準備をしていますが、質問の1つは次のとおりです。デフォルトのクラスコンストラクターを削除できますか? OK、だから明らかにあなたはそれを行うことができます:

class MyClass 
{ 
  public: 
    MyClass() = delete; 
};

しかし、なぜあなたはそれをするのか分かりませんか?

47
Derek Johnson

次のクラスを検討してください。

struct Foo {
    int i;
};

このクラスは集約であり、次の3つの定義すべてでインスタンスを作成できます。

int main() {
    Foo f1;     // i uninitialized
    Foo f2{};   // i initialized to zero
    Foo f3{42}; // i initialized to 42
}

ここで、初期化されていない値とそれらが生成する可能性のある未定義の動作が気に入らないとしましょう。 Fooのデフォルトコンストラクターを削除できます。

struct Foo {
    Foo() = delete;
    int i;
};

Fooは依然として集約ですが、後者の2つの定義のみが有効です。最初の定義はコンパイル時エラーになりました。

72
Quentin

デフォルトのコンストラクタを削除する理由はいくつかあります。

  1. クラスは純粋に静的であり、静的メソッド/メンバーのみでクラスをインスタンス化することは望ましくありません。このようなクラスの例としては、静的メソッドのみを使用して新しいクラスを作成するファクトリデザインパターンを実装するものがあります。
  2. クラスがデフォルトのコンストラクタを持つことは意味がありません(パラメータが必要であるため/クラスにとって意味のあるデフォルト値はありません)。この場合、= deleteは@HolyBlackCatが言ったようにスタイルのことですが、クライアントコードにonlyを指定してコンストラクターを呼び出すことで意図を明確にします。
  3. 集計クラスの初期化されていないデータは必要ありません。

2番目のステートメントが明確でない場合は、次の例を検討してください。

class A
{
public:
   //A() = delete; 
   A(int, int) {};
};

今すぐデフォルトのコンストラクターを呼び出そうとすると、次のようなエラーが表示されます(GCC 7.2):

エラー: 'A :: A()'の呼び出しに一致する関数がありません

ただし、= deleteで行のコメントを外した場合、次のようになります。

エラー:削除された関数 'A :: A()'の使用

これにより、一方が他のエラーと比較して削除されたコンストラクターを使用しようとしていることが明確になります。

45
Arnav Borborah

複数のデフォルト選択

クラスのデフォルトコンストラクターを削除することは、デフォルトまたは初期化されていない状態に対して複数の選択肢がある場合に有効です。たとえば、クラスがあるとします。

_template<typename F>
class Polynomial;
_

フィールドF上の多項式を表します。この場合、多項式のデフォルト値には多くの選択肢があります。 1つは、加算中の多項式の恒等式、つまり0である可能性がありますが、乗法的な恒等式、ユニティも使用できます。ユーザーがどのようにクラスを推論するか、どのように使用されるかによって異なります。


デフォルトの選択なし

もう1つの注目すべきケースは、意味のある複数のデフォルト状態ではなく、何も存在しない場合です。たとえば、多様体または表面を表すクラスがあるとします。

Manifold()とは何ですか?それは何もない、表面もない、距離や距離の概念がない、空の空間です。しかし、それを多様体と考えるのは理にかなっていないが、むしろトポロジー空間のようなもっと一般的なものだろう。

したがって、この場合、デフォルトのコンストラクタも削除することを選択します。

5
user1997744

クラスがインスタンス化されることを意図していない場合があります。

これまで言及されていない1つの例は、「特性」クラスです。たとえば、 std::char_traits 、標準ではデフォルトのコンストラクタを削除する必要があるとは言われていませんが、クラス自体が空であり、すべての関数が静的であり、インスタンス化する必要がないため、デフォルトのコンストラクタはほとんど役に立ちませんそれが提供する型エイリアスを使用します。

特性クラスは通常、他のクラス(通常は他のテンプレートクラス)をサポートするためにのみ使用されるため、多くの場合、デフォルトのコンストラクタを削除するのが理にかなっています。オブジェクト。

5
Pharap