1. ホーム
  2. c++

[解決済み】デフォルトのコンストラクタとデストラクタの「=default」は「{}」とどう違うのですか?

2022-04-10 12:55:43

質問

当初はデストラクタについてのみの質問として投稿しましたが、今回、デフォルトコンストラクタについての考察を追加します。 以下は元の質問です。

自分のクラスに仮想のデストラクタを与えたいが、それは それ以外はコンパイラが生成するものと同じです。 =default :

class Widget {
public:
   virtual ~Widget() = default;
};

しかし、より少ないタイプ数で同じ効果を得るには、次のようにします。 空の定義

class Widget {
public:
   virtual ~Widget() {}
};

この2つの定義が異なる動作をする方法はあるのでしょうか?

この質問に対して投稿された返信を見ると、デフォルトのコンストラクタの状況も似ているようです。 とquot.の間にほとんど意味の違いがないことを考えると、quot.quot; =default と、" {} デストラクタの場合は "ですが、デフォルトのコンストラクタの場合も同様に、これらのオプションにほとんど意味の違いはないのでしょうか? つまり、ある型を作成し、その型のオブジェクトが生成も破壊もされると仮定した場合、なぜ次のように記述したいのでしょうか。

Widget() = default;

ではなく

Widget() {}

?

この質問を最初に投稿した後に拡張することは、SOのルールに違反しているとしたら申し訳ありません。 デフォルトのコンストラクタのためにほとんど同じ質問を投稿することは、あまり望ましくない選択肢であると感じました。

どのように解決するのですか?

これは、コンストラクタとデストラクタについて尋ねる場合、全く異なる質問です。

もし、デストラクタが virtual であれば、その差はごくわずかです。 ハワードが指摘したように . しかし、もしあなたのデストラクタが 非仮想 となると、全く別の話になってしまいます。コンストラクターも同様です。

使用方法 = default 構文は、特殊なメンバ関数 (デフォルト コンストラクタ、コピー/移動コンストラクタ/代入、デストラクタなど) に対して、単に {} . 後者の場合、その関数はユーザが提供するものになります。そして、それがすべてを変えてしまうのです。

C++11の定義では、これは些細なクラスです。

struct Trivial
{
  int foo;
};

デフォルトでコンストラクタを作ろうとすると、コンパイラは自動的にデフォルトのコンストラクタを生成します。コピー/移動、デストラクトも同様です。ユーザーがこれらのメンバ関数を一切提供しなかったため、C++11の仕様では、これを"trivial"クラスとみなしています。したがって、それらの内容をmemcpyして初期化するなど、合法的に行うことができます。

これは

struct NotTrivial
{
  int foo;

  NotTrivial() {}
};

名前が示すように、これはもはや些細なことではありません。ユーザが用意するデフォルトのコンストラクタを持ちます。空でもかまいません。C++11 の規則に関する限り、これは些細な型ではありえません。

これです。

struct Trivial2
{
  int foo;

  Trivial2() = default;
};

これも名前が示すように、これはつまらない型です。なぜか?コンパイラにデフォルトのコンストラクタを自動的に生成するように指示したからです。したがって、このコンストラクタはユーザが提供するものではありません(quot; user-provided." user-provided default constructorがないため、この型はトリビアルとみなされます)。

この = default 構文は、主にコピーコンストラクタやアサイメントのような関数の作成を防ぐメンバ関数を追加するときに使用します。しかし、これはコンパイラが特別な動作をするきっかけにもなるので、デフォルトのコンストラクタやデストラクタでも有用です。