名前空間
変種
操作

デフォルト初期化

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

これは、初期化子なしでオブジェクトが構築されるときに実行される初期化です。

目次

[編集] 構文

T object ; (1)
new T (2)

[編集] 解説

デフォルト初期化は3つの状況で実行されます。

1) 自動、静的、またはスレッドローカルのストレージ期間を持つ変数が、初期化子なしで宣言された場合;
2) 動的ストレージ期間を持つオブジェクトが、初期化子なしのnew-式によって作成された場合;
3) 基底クラスまたは非静的データメンバがコンストラクタ初期化子リストで言及されず、そのコンストラクタが呼び出された場合。

デフォルト初期化の効果は次のとおりです。

  • T が (cv修飾子が付いている可能性のある) 非POD(C++11まで) クラス型である場合、コンストラクタが考慮され、空の引数リストに対してオーバーロード解決が実行されます。選択されたコンストラクタ (これはデフォルトコンストラクタの1つです) が、新しいオブジェクトの初期値を提供するために呼び出されます;
  • T が配列型である場合、配列のすべての要素がデフォルト初期化されます;
  • それ以外の場合、初期化は実行されません (を参照)。

[編集] const オブジェクトのデフォルト初期化

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

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

初期化子が使用されていない場合、自動ストレージ期間を持つ (cv修飾子が付いている可能性のある) 非PODクラス型 (またはその配列) のみがデフォルト初期化されると見なされていました。スカラー型と動的ストレージ期間を持つPOD型は初期化されないと見なされていました (C++11以降、この状況はデフォルト初期化の一種として再分類されました)。

(C++11まで)
  • T の各直接非静的データメンバ M がクラス型 X (またはその配列) であり、X が const-default-constructibleであり、かつ
  • T に直接バリアントメンバがなく、かつ
(C++11まで)
  • T の各直接非バリアント非静的データメンバ Mデフォルトメンバ初期化子を持つか、または M がクラス型 X (またはその配列) である場合、X が const-default-constructibleであり、
  • T が少なくとも1つの非静的データメンバを持つ共用体である場合、ちょうど1つのバリアントメンバがデフォルトメンバ初期化子を持ち、
  • T が共用体でない場合、少なくとも1つの非静的データメンバを持つ各無名共用体メンバ (もしあれば) に対して、ちょうど1つの非静的データメンバがデフォルトメンバ初期化子を持ち、かつ
(C++11以降)

T の各潜在的に構築される基底クラスが const-default-constructibleであること。

[編集] 不定値とエラー値

自動または動的ストレージ期間を持つオブジェクトのストレージが取得されるとき、そのオブジェクトは不定値を持ちます。

オブジェクトに対して初期化が実行されない場合、そのオブジェクトはその値が置き換えられるまで不定値を保持します。

(C++26まで)

自動または動的ストレージ期間を持つオブジェクトのストレージが取得されるとき、そのオブジェクトのストレージを構成するバイトは、以下の初期値をとります。

  • オブジェクトが動的ストレージ期間を持つ場合、または、最初の宣言が[[indeterminate]]でマークされた変数または関数パラメータに関連付けられたオブジェクトである場合、バイトは不定値を持ちます。
  • それ以外の場合、バイトはエラー値を持ち、各値はプログラムの状態とは独立して実装によって決定されます。

オブジェクト (そのサブオブジェクトを含む) に対して初期化が実行されない場合、そのようなバイトはその値が置き換えられるまで初期値を保持します。

  • 値表現のいずれかのビットが不定値を持つ場合、そのオブジェクトは不定値を持ちます。
  • それ以外の場合、値表現のいずれかのビットがエラー値を持つ場合、そのオブジェクトはエラー値を持ちます。
(C++26以降)

評価が不定値を生成する場合、動作は未定義です。

評価がエラー値を生成する場合、動作はエラーです。

(C++26以降)

[編集] 特殊なケース

以下の型は未初期化対応 (uninitialized-friendly)です。

(C++17以降)
  • unsigned char
  • char, その基底型がunsigned charの場合

不定またはエラー(C++26以降)value が与えられた場合、value未初期化結果値は次のようになります。

  • value が不定値でもある場合、不定値。
  • value がエラー値である場合、value
(C++26以降)

評価evalが未初期化対応型 (uninitialized-friendly type) の不定またはエラー(C++26以降)value を生成する場合、以下のケースで動作は適切に定義されます。

  • eval は以下の式およびオペランドのいずれかの評価である場合:
この場合、操作の結果はvalueの未初期化結果値です。
  • eval は、左オペランドが未初期化対応型のlvalueである単純代入演算子の右オペランドの評価である場合。
この場合、左オペランドによって参照されるオブジェクトの値は、value の未初期化結果値に置き換えられます。
  • eval は、未初期化対応型のオブジェクトを初期化する際の初期化式の評価である場合。
  • 初期化されるオブジェクトがstd::byte型ではない場合、valuestd::byte型であってはなりません。
(C++17以降)
この場合、そのオブジェクトはvalueの未初期化結果値に初期化されます。

未初期化対応型の不定値を変換すると、不定値が生成されます。

未初期化対応型のエラー値を変換すると、エラー値が生成され、変換の結果は変換されたオペランドの値となります。

(C++26以降)
// Case 1: Uninitialized objects with dynamic storage duration
// All C++ versions: indeterminate value + undefined behavior
int f(bool b)
{
    unsigned char* c = new unsigned char;
    unsigned char d = *c; // OK, “d” has an indeterminate value
    int e = d;            // undefined behavior
    return b ? d : 0;     // undefined behavior if “b” is true
}
 
// Case 2: Uninitialized objects with automatic storage duration
// until C++26: indeterminate value + undefined behavior
// since C++26: erroneous value + erroneous behavior
int g(bool b)
{
    unsigned char c;     // “c” has an indeterminate/erroneous value
 
    unsigned char d = c; // no undefined/erroneous behavior,
                         // but “d” has an indeterminate/erroneous value
 
    assert(c == d);      // holds, but both integral promotions have
                         // undefined/erroneous behavior
 
    int e = d;           // undefined/erroneous behavior
    return b ? d : 0;    // undefined/erroneous behavior if “b” is true
}
 
// Same as case 2
void h()
{
    int d1, d2;  // “d1” and “d2” have indeterminate/erroneous values
    int e1 = d1; // undefined/erroneous behavior
    int e2 = d1; // undefined/erroneous behavior
 
    assert(e1 == e2); // holds
    assert(e1 == d1); // holds, undefined/erroneous behavior
    assert(e2 == d1); // holds, undefined/erroneous behavior
 
    // no undefined/erroneous behavior,
    // but “d2” has an indeterminate/erroneous value
    std::memcpy(&d2, &d1, sizeof(int));
 
    assert(e1 == d2); // holds, undefined/erroneous behavior
    assert(e2 == d2); // holds, undefined/erroneous behavior
}

[編集] 注釈

参照およびconstスカラーオブジェクトはデフォルト初期化できません。

機能テストマクロ 規格 機能
__cpp_constexpr 201907L (C++20) constexpr関数内の自明なデフォルト初期化とasm-宣言

[編集]

#include <string>
 
struct T1 { int mem; };
 
struct T2
{
    int mem;
    T2() {} // “mem” is not in the initializer list
};
 
int n; // static non-class, a two-phase initialization is done:
       // 1) zero-initialization initializes n to zero
       // 2) default-initialization does nothing, leaving n being zero
 
int main()
{
    [[maybe_unused]]
    int n;            // non-class, the value is indeterminate
    std::string s;    // class, calls default constructor, the value is ""
    std::string a[2]; // array, default-initializes the elements, the value is {"", ""}
//  int& r;           // Error: a reference
//  const int n;      // Error: a const non-class
//  const T1 t1;      // Error: const class with implicit default constructor
    [[maybe_unused]]
    T1 t1;            // class, calls implicit default constructor
    const T2 t2;      // const class, calls the user-provided default constructor
                      // t2.mem is default-initialized
}

[編集] 欠陥レポート

以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。

DR 適用対象 公開された動作 正しい動作
CWG 178 C++98 値初期化が存在しなかった;
空の初期化子はデフォルト初期化を呼び出した
(ただしnew T()もゼロ初期化を実行する)
空の初期化子は以下を呼び出す
値初期化
CWG 253 C++98 constオブジェクトのデフォルト初期化は
暗黙的に宣言されたデフォルトコンストラクタを呼び出すことができなかった
すべてのサブオブジェクトが初期化されている場合は許可
CWG 616 C++98 任意の未初期化オブジェクトの
lvalueからrvalueへの変換は常にUBだった
不定のunsigned charは許可される
CWG 1787 C++98 不定のunsigned charからの読み出しは
レジスタにキャッシュされていてもUBだった
符号ビットにシフトする動作は定義された

[編集] 関連項目

English 日本語 中文(简体) 中文(繁體)