名前空間
変種
操作

値初期化(C++03およびそれ以降)

提供: cppreference.com
< cpp‎ | language
 
 
C++言語
一般的なトピック
フロー制御
条件付き実行文
繰り返し文 (ループ)
ジャンプ文
関数
関数宣言
ラムダ関数宣言
inline 指定子
例外指定 (非推奨)
noexcept 指定子 (C++11)
例外
名前空間
指定子
decltype (C++11)
auto (C++11)
alignas (C++11)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点
文字 - 文字列 - nullptr (C++11)
ユーザ定義 (C++11)
ユーティリティ
属性 (C++11)
typedef 宣言
型エイリアス宣言 (C++11)
キャスト
暗黙の変換 - 明示的な変換
static_cast - dynamic_cast
const_cast - reinterpret_cast
メモリ確保
クラス
クラス固有の関数特性
特別なメンバ関数
テンプレート
その他
 
 

変数が空の初期化子で構築されたときに行われる初期化です。

目次

[編集] 構文

T() (1)
new T () (2)
Class::Class(...) : member() { ... } (3)
T object {}; (4) (C++11およびそれ以降)
T{} (5) (C++11およびそれ以降)
new T {} (6) (C++11およびそれ以降)
Class::Class(...) : member{} { ... } (7) (C++11およびそれ以降)

[編集] 説明

値初期化は以下の状況で行われます。

1,5) 名前なしの一時オブジェクトが空の括弧または波括弧 (C++11およびそれ以降)から構成される初期化子を用いて作成されたとき。
2,6) 動的記憶域期間を持つオブジェクトが空の括弧または波括弧 (C++11およびそれ以降)から構成される初期化子を用いて作成されたとき。
3,7) 非静的データメンバまたは基底クラスが空の括弧または波括弧 (C++11およびそれ以降)メンバ初期化子を用いて初期化されたとき。
4) 名前付きの変数 (自動、静的、またはスレッドローカル) が空の波括弧から構成される初期化子を用いて宣言されたとき。
(C++11およびそれ以降)

すべての場合において、空の波括弧 {} が使用され、 T集成体型の場合は、値初期化の代わりに集成体初期化が行われます。

T がデフォルトコンストラクタを持たないけれども std::initializer_list を取るコンストラクタを持つクラス型の場合は、リスト初期化が行われます。

値初期化の効果は以下の通りです。

1) T が何らかの種類のユーザ提供コンストラクタを少なくともひとつ持つ場合は、デフォルトコンストラクタが呼ばれます。
(C++11以前)
1) T がデフォルトコンストラクタを持たないまたはユーザ提供のデフォルトコンストラクタを持つまたは削除されたデフォルトコンストラクタを持つクラス型の場合、オブジェクトはデフォルト初期化されます。
(C++11およびそれ以降)
2) T がいかなるユーザ提供のコンストラクタも持たない非 union クラス型の場合は、 T のすべての非静的データメンバおよび基底クラスのコンポーネントが値初期化されます。
(C++11以前)
2) T がユーザ提供でなく削除されていないデフォルトコンストラクタを持つクラス型 (つまり、暗黙に定義されたまたはデフォルト化されたデフォルトコンストラクタを持つクラス) の場合は、オブジェクトはゼロ初期化され、非トリビアルなデフォルトコンストラクタを持つ場合は、オブジェクトはデフォルト初期化されます。
(C++11およびそれ以降)
3) T が配列型の場合は、配列の各要素が値初期化されます。
4) そうでなければ、オブジェクトはゼロ初期化されます。

[編集] ノート

コンストラクタがユーザによって宣言され、その最初の宣言が明示的にデフォルト化されていない場合、そのコンストラクタはユーザ提供されていると言います。

構文 T object(); は、オブジェクトを初期化するのではなく、引数を取らず T を返す関数を宣言します。 C++11 より前で名前付き変数を値初期化する方法は T object = T(); です。 これは一時オブジェクトを値初期化し、それからオブジェクトをコピー初期化します。 この場合ほとんどのコンパイラは最適化によってコピーを省略します。

C++03 (値初期化が導入された) より前の C++98 では、式 new T() はデフォルト初期化として分類され、ゼロ初期化が規定されていました。

参照は値初期化できません。

関数キャストで説明されている通り、配列に対しては構文 T() (1) は禁止されていますが、 T{} (5) は許されています。

すべての標準のコンテナ (std::vectorstd::list など) は、単一の size_type 引数を用いて構築されたとき、または resize() の呼び出しによって拡張されたとき、その要素を値初期化します。

C++11 以降、ユーザ提供コンストラクタを持つクラス型のメンバを持つユーザ提供コンストラクタを持たないクラスの値初期化は、そのコンストラクタを呼ぶ前にそのメンバをゼロクリアします。

struct A
{
    int i;
    A() { } // ユーザ提供デフォルトコンストラクタ (i を初期化しない)
};
 
struct B { A a; }; // 暗黙に定義されたデフォルトコンストラクタ
 
std::cout << B().a.i << '\n'; // 一時オブジェクト B を値初期化します。
                              // C++03 では b.a.i は未初期化になります。
                              // C++11 では b.a.i はゼロに設定されます。
// (C++11 では B{}.a.i は b.a.i を未初期化にしますが、理由は異なります。
// DR1301 以降の C++11 では、 B{} は集成体初期化であり、
// それはユーザ提供コンストラクタを持つ A を値初期化します)。

[編集]

#include <string>
#include <vector>
#include <iostream>
 
struct T1
{
    int mem1;
    std::string mem2;
}; // 暗黙のデフォルトコンストラクタ。
 
struct T2
{
    int mem1;
    std::string mem2;
    T2(const T2&) { } // ユーザ定義コピーコンストラクタ。
};                    // デフォルトコンストラクタはありません。
 
struct T3
{
    int mem1;
    std::string mem2;
    T3() { } // ユーザ定義デフォルトコンストラクタ。
};
 
std::string s{}; // クラス → デフォルト初期化、値は ""。
 
int main()
{
    int n{};                // スカラー → ゼロ初期化、値は 0。
    double f = double();    // スカラー → ゼロ初期化、値は 0.0。
    int* a = new int[10](); // 配列 → 各要素の値初期化、各要素の値は 0。
    T1 t1{};                // 暗黙のデフォルトコンストラクタを持つクラス →
                            //     t1.mem1 はゼロ初期化、値は 0。
                            //     t1.mem2 はデフォルト初期化、値は ""。
//  T2 t2{};                // デフォルトコンストラクタを持たないクラス → エラー。
    T3 t3{};                // ユーザ定義デフォルトコンストラクタを持つクラス →
                            //     t3.mem1 はデフォルト初期化、値は不定。
                            //     t3.mem2 はデフォルト初期化、値は ""。
    std::vector<int> v(3);  // 各要素の値初期化、各要素の値は 0。
    std::cout << s.size() << ' ' << n << ' ' << f << ' ' << a[9] << ' ' << v[2] << '\n';
    std::cout << t1.mem1 << ' ' << t3.mem1 << '\n';
    delete[] a;
}

出力例:

0 0 0 0 0
0 4199376

[編集] 欠陥報告

以下の動作変更欠陥報告は以前に発行された C++ 標準に遡って適用されました。

DR 適用先 発行時の動作 正しい動作
CWG 1301 C++11 defaulted default constructor skipped zero-init before construction zero-init performed

[編集] 関連項目