Namespaces
Variants

Value-initialization

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

これは、空の初期化子でオブジェクトが構築された際に実行される初期化です。

目次

構文

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) 動的ストレージ期間を持つオブジェクトが new によって作成され、初期化子が空の括弧の組 または波括弧 (C++11以降) で構成されている場合;
3,7) 非静的データメンバーまたは基底クラスが空の丸括弧のペア メンバー初期化子 を使用して初期化される場合 または波括弧 (C++11以降) ;
4) 名前付きオブジェクト(自動、静的、またはスレッドローカル)が、一対の波括弧からなる初期化子で宣言された場合。

すべての場合において、空の中括弧のペア {} が使用され、かつ T が集成体型である場合、 aggregate initialization が値初期化の代わりに実行されます。

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

(C++11以降)

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

  • T が(CV修飾された可能性のある)クラス型の場合:
  • それ以外の場合、 T が配列型であれば、配列の各要素は値初期化されます。
  • それ以外の場合、オブジェクトはゼロ初期化されます。

注記

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

注意点: - HTMLタグと属性はそのまま保持 - ` `タグ内の`T`は翻訳対象外 - C++特有の用語(value-initialize, copy-initialize, copy elisionなど)は専門用語としてそのまま使用 - 構文例は完全に保持 - 技術文書としての正確性と専門性を維持

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

function-style cast で説明されているように、 T ( ) (1) の構文は T が配列型を指定する場合に禁止されますが、 T { } (5) は許可されます。

すべての標準コンテナ( std::vector std::list など)は、単一の size_type 引数で構築された場合、または resize ( ) の呼び出しによって拡張された場合、その要素を値初期化します。ただし、アロケータが construct の動作をカスタマイズしている場合は除きます。

#include <cassert>
#include <iostream>
#include <string>
#include <vector>
struct T1
{
    int mem1;
    std::string mem2;
    virtual void foo() {} // T1が集成体でないことを保証
}; // 暗黙のデフォルトコンストラクタ
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
    assert(n == 0);
    double f = double();    // スカラー型 => ゼロ初期化、値は0.0
    assert(f == 0.0);
    int* a = new int[10](); // 配列 => 各要素の値初期化
    assert(a[9] == 0);      //          各要素の値は0
    T1 t1{};                // 暗黙のデフォルトコンストラクタを持つクラス =>
    assert(t1.mem1 == 0);   //     t1.mem1はゼロ初期化され、値は0
    assert(t1.mem2 == "");  //     t1.mem2はデフォルト初期化され、値は""
//  T2 t2{};                // エラー: デフォルトコンストラクタのないクラス
    T3 t3{};                // ユーザー提供のデフォルトコンストラクタを持つクラス =>
    std::cout << t3.mem1;   //     t3.mem1はデフォルト初期化され不定値
    assert(t3.mem2 == "");  //     t3.mem2はデフォルト初期化され、値は""
    std::vector<int> v(3);  // 各要素の値初期化
    assert(v[2] == 0);      // 各要素の値は0
    std::cout << '\n';
    delete[] a;
}

出力例:

42

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
CWG 178 C++98 値初期化は存在せず、空の初期化子はデフォルト初期化を呼び出していた
(ただし new T ( ) はゼロ初期化も実行する)
空の初期化子は
値初期化を呼び出す
CWG 543 C++98 ユーザー提供コンストラクタを持たないクラスオブジェクトの値初期化は、
各サブオブジェクトを値初期化することと等価だった
(ユーザー提供デフォルトコンストラクタを持つメンバーのゼロ初期化は不要)
オブジェクト全体を
ゼロ初期化し、
その後デフォルト
コンストラクタを呼び出す
CWG 1301 C++11 削除されたデフォルトコンストラクタを持つ共用体の
値初期化はゼロ初期化につながっていた
それらは
デフォルト初期化される
CWG 1368 C++98 ユーザー提供コンストラクタがあると
ゼロ初期化がスキップされていた
ユーザー提供の
デフォルトコンストラクタ
のみがゼロ初期化をスキップする
CWG 1502 C++11 ユーザー提供デフォルトコンストラクタを持たない共用体の
値初期化は、デフォルトメンバー初期化子があるにもかかわらず、
オブジェクトのゼロ初期化のみを行っていた
ゼロ初期化後に
デフォルト初期化を
実行する
CWG 1507 C++98 ユーザー提供コンストラクタを持たないクラスオブジェクトの
値初期化は、デフォルトコンストラクタがトリビアルな場合に
その有効性をチェックしなかった
トリビアルな
デフォルトコンストラクタの
有効性がチェックされる
CWG 2820 C++98 ゼロ初期化に続くデフォルト初期化には
非トリビアルなコンストラクタが必要だった
不要
CWG 2859 C++98 クラスオブジェクトの値初期化は、デフォルト初期化が
実際にユーザー提供コンストラクタを選択しない場合でも
ゼロ初期化を含む可能性があった
この場合
ゼロ初期化は
行われない

関連項目