20

C ++ 11には、特別なメンバー関数のデフォルト実装を作成するようにコンパイラーに指示する機能が追加されています。関数を削除することの価値はわかりますが、関数を明示的にデフォルト設定することの価値はどこにありますか?空白のままにしておくと、コンパイラがとにかくそれを行います。

私が見ることができる唯一のポイントは、デフォルトのコンストラクターは、他のコンストラクターが存在しない場合にのみ作成されるということです。

class eg {
public:
    eg(int i);
    eg() = default; 
};

しかし、それはあなたが今それをする方法より本当に良いですか?

class eg {
public:
    eg(int i);
    eg() {}
};

または、ユースケースがありませんか?

4

8 に答える 8

19

デフォルトのコンストラクターには宣言があり、その宣言は通常のアクセス規則に従います。たとえば、デフォルトのコピーコンストラクタを保護することができます。これらの新しい宣言がない場合、デフォルトで生成されるメンバーはパブリックになります。

于 2009-05-05T09:04:01.393 に答える
17

StroustrupのWebサイトからのこれらの例は、要点を理解するのに役立つ場合があります。

デフォルトおよび削除された機能-デフォルトの制御

「コピーの禁止」の一般的なイディオムを直接表現できるようになりました。

class X {
  // ...

  X& operator=(const X&) = delete;    // Disallow copying
  X(const X&) = delete;
};

逆に、デフォルトのコピー動作が必要であると明示的に言うこともできます。

class Y {
  // ...
  Y& operator=(const Y&) = default;   // default copy semantics
  Y(const Y&) = default;

};

デフォルトについて明示することは明らかに冗長ですが、その効果に対するコメントと(さらに悪いことに)デフォルトの動作を与えることを意図したコピー操作を明示的に定義するユーザーは珍しいことではありません。デフォルトの動作を実装するためにコンパイラに任せることは、より単純で、エラーが発生しにくく、多くの場合、より良いオブジェクトコードにつながります。「デフォルト」メカニズムは、デフォルトを持つすべての関数に使用できます。「削除」メカニズムは、どの機能にも使用できます。たとえば、次のように不要な変換を排除できます。

struct Z {
  // ...

  Z(long long);     // can initialize with an long long
  Z(long) = delete; // but not anything less
};
于 2009-05-05T09:34:26.047 に答える
12

生成された関数のアクセシビリティ(プライベート/保護)を変更するだけでなく、それらを仮想化することができます。

struct S
{
    virtual ~S();
    virtual S& operator=(const S&);
};

S::~S() = default;
S& S::operator=(const S&) = default;

デフォルトの関数の次の側面を変更できます。

  • アクセス(非公開にする)
  • バーチャル
  • 明示的(コンストラクター)
  • 例外仕様
  • パラメータの定数

ただし、そのためには、関数をクラスの外部で定義する必要があります(C++0x最終委員会ドラフトの8.4.2/2 )。

ローレンスクラウルによる元の提案のバージョンはここにあります。

明確化と引用をしてくれたRogerPateに感謝します。

于 2009-05-05T10:04:35.057 に答える
2

1)暗黙的に生成されたデストラクタは、現在仮想ではありません。したがって、それらを仮想化するためにそれらを定義する必要があります。その場合、それらはそれほど効率的ではありません。= defaultを使用すると、暗黙的に生成されたデストラクタとして仮想と効率の両方が得られます。

2)暗黙的に生成されたものとは異なり、アクセス指定子があります。

3)デフォルトのコンストラクターをインライン化した場合でも、クラスは簡単なままです。

これは、この新機能を詳しく説明した記事です。

于 2009-05-05T10:31:14.757 に答える
1

コピーコンストラクターをデフォルトで生成できることは実際に役立つと思います。あなたが言うようにあなたがタイプする実装はより短いので、私はデフォルトのコンストラクターを生成するデフォルトの使用法を見ることができません。

于 2009-05-05T08:55:36.860 に答える
1

ScottMeyerのすばらしい本「EffectiveModernC++」のアイテム17を参照してください。デフォルトのコピーコンストラクター、コピー操作、および移動操作が生成される(または生成されない)多くの条件について説明します。

言い換えれば、コンパイラは「とにかくそれをしない」かもしれません。ただし、デフォルトの特殊メンバー関数が意味をなす場合、ユーザーは「default」キーワードを使用して、他の方法では生成されないデフォルト関数を生成するようにコンパイラーに明示的に指示できます。

項目17の最後にある覚えておくべきことから:

  • 移動操作は、明示的に宣言された移動操作、コピー操作、またはデストラクタがないクラスに対してのみ生成されます。

  • コピーコンストラクターは、明示的に宣言されたコピーコンストラクターがないクラスに対してのみ生成され、移動操作が宣言されている場合は削除されます。コピー代入演算子は、明示的に宣言されたコピー代入演算子がないクラスに対してのみ生成され、移動操作が宣言されている場合は削除されます。デストラクタが明示的に宣言されているクラスでのコピー操作の生成は非推奨になりました。

于 2016-11-03T16:35:12.807 に答える
0

多くの属性を持つクラスがある場合、デフォルト設定はコピーコンストラクターにとってより便利です。たとえば、このクラスがある場合:

class MyClass {
private:
   int offset;
   std::string name;
   std::vector<Person*> relatives;
   float weight;
   MyClass* spouse;
   Vehicle* car;
   double houseArea;
   Date birth;
   Person* parents[2];

public:
   /* Default constructor will be defined here */
};

このようにコピーコンストラクタを定義する代わりに、次のようにします。

MyClass(const MyClass& that) :
   offset(that.offset),
   name(that.name),
   relatives(that.relatives),
   weight(that.weight),
   spouse(that.spouse),
   car(that.car),
   houseArea(that.houseArea),
   birth(that.birth),
   parents(that.parents)
{}

次のように定義します。

MyClass(const MyClass&) = default;
于 2011-09-07T01:46:16.213 に答える
0

私にとっては、その無効化機能が役立ちます。現在作成しているほとんどのクラスでは、コピーと割り当てを無効にします。リンカーエラーに依存するのではなく、コンパイラーがこれを行うために認識できる機能があると便利です。

于 2009-05-05T09:01:33.413 に答える