1. ホーム
  2. c++

[解決済み] なぜC++はconstオブジェクトをデフォルトで構築するために、ユーザが提供するデフォルトコンストラクタを必要とするのでしょうか?

2023-02-23 04:16:11

疑問点

C++の規格(8.5項)には、以下のように書かれています。

プログラムが const-qualified型Tのオブジェクトのデフォルト初期化を呼び出す場合、Tはユーザが提供するデフォルトコンストラクタを持つクラス型でなければならない。

なぜでしょうか?この場合、ユーザ提供のコンストラクタが必要な理由が思いつきません。

struct B{
  B():x(42){}
  int doSomeStuff() const{return x;}
  int x;
};

struct A{
  A(){}//other than "because the standard says so", why is this line required?

  B b;//not required for this example, just to illustrate
      //how this situation isn't totally useless
};

int main(){
  const A a;
}

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

これは(すべてのバージョンの規格に対して)欠陥とみなされ、次のようにして解決されました。 コアワーキンググループ (CWG) 不具合 253 . 規格の新しい文言では http://eel.is/c++draft/dcl.init#7

以下の場合、クラス型Tはconst-default-constructibleです。 T のデフォルト初期化でユーザが提供するコンストラクタが呼び出される場合や を呼び出す場合、または、(基底クラスから継承されていない)

  • T の各直接非変数非静的データメンバー M がデフォルトメンバー初期化子を持つか、M がクラス型 X(またはその配列)である場合、X が const-default-constructible である場合。
  • T が少なくとも一つの非静的データメンバを持つユニオンである場合、ちょうど一つのバリアントメンバがデフォルトメンバイニシャライザを持つ。
  • T がユニオンでない場合、少なくとも一つの非静的データメンバを持つ各匿名ユニオンメンバ (もしあれば) に対して、正確に一つの非静的データ メンバはデフォルトメンバイニシャライザを持ち
  • T の各潜在的に構築された基底クラスは const-default-constructible である。

のオブジェクトのデフォルト初期化を要求する場合,Tはconst-default-constructibleクラスでなければならない。 のオブジェクトのデフォルト初期化を要求する場合,Tはconst-default-constructibleなクラス型またはその配列でなければならない。 型またはその配列でなければなりません。

この文言は、本質的に明白なコードが機能することを意味します。すべてのベースとメンバを初期化すれば、次のようになります。 A const a; と言うことができます。これは、どのように、あるいはどのようなコンストラクタを綴るかに関係なく、です。

struct A {
};
A const a;

gcc は 4.6.4 からこれを受け入れています。clang は 3.9.0 からこれを受け入れています。Visual Studio もこれを受け入れています (少なくとも 2017 年、もっと早いかどうかは不明)。