9

次のコードを検討してください。

#include <iostream>

template<class T>
void f(T& t)
{
    t = T();
}

int main()
{
    int x = 42;
    f(x);
    std::cout << x;
}

C++11 標準は、出力がどうあるべきかを定義していますか? 私のコンパイラは 0 を出力しますが、プリミティブ型のデフォルトのコンストラクタは null 操作または未定義の動作であるという印象を受けました。

4

2 に答える 2

18

コードに含まれる「デフォルトコンストラクタ」はありません。クラス型のみがコンストラクターを持つことができます。スカラー型には、デフォルトまたはそれ以外のコンストラクターはありません。

構文は、T()いわゆるvalue-initializationによって初期化された一時オブジェクトを作成します。値の初期化は、クラスタイプのみ、およびユーザー定義のコンストラクター(C ++ 11ではいくつかのニュアンスがある)を持つコンストラクター呼び出しにのみ解決されます。他のタイプの場合、値の初期化にはコンストラクターはまったく含まれません。これは、コンストラクターを使用せずに、データの初期値を直接定義する独自のかなり複雑な初期化ルールに従って進行します(言語仕様の8.5を参照)。

スカラー型の場合、value-initializationはゼロ初期化を実行します。これが、コードがゼロを出力することが保証されている理由です。抽象初期化プロセスの正確な詳細は、C ++言語標準のバージョン間で変更されましたが、時代の初めから、C++言語はT()T == intがゼロに評価されることを保証していました。つまり、C ++ 98でも、コードはゼロを出力します。

T(...)これらすべての式がどういうわけかコンストラクター呼び出しを必然的に暗示しているというのはよくある誤解です。実際には、T(...)式は(引数の数に関係なく)機能的なキャスト式であり(言語仕様の5.2.3を参照)、特定の状況の狭いセットでコンストラクター呼び出しに解決される可能性があり、のコンストラクターとは関係ありません。他の状況。

たとえば、このコード

struct S { int x, y; };

S s = S();

クラスにはデフォルトのコンストラクターがあるにもかかわらず、sゼロ(s.xとの両方)で初期化されることが保証されています。この例は、デフォルトのコンストラクターが存在する状況でも、式がそれを完全に無視し、代わりに独自のルールで機能するという事実を具体的に示すために作成しました。s.yST()

于 2012-11-16T07:55:03.627 に答える
4

これがあなたの質問に関して標準が言っていることです:

8.5でパラグラフ10:

初期化子が空の括弧のセット、つまり()であるオブジェクトは、値で初期化されます。


8.5でパラグラフ7:

タイプTのオブジェクトを値初期化するということは、次のことを意味します。

  • Tがユーザー提供のコンストラクター(12.1)を持つ(おそらくcv修飾された)クラスタイプ(条項9)の場合、Tのデフォルトコンストラクターが呼び出されます(Tにアクセス可能なデフォルトコンストラクターがない場合、初期化は不正な形式になります) ;
  • Tがユーザー提供のコンストラクターのない(おそらくcv修飾された)非ユニオンクラスタイプである場合、オブジェクトはゼロで初期化され、Tの暗黙的に宣言されたデフォルトコンストラクターが自明でない場合、そのコンストラクターが呼び出されます。
  • Tが配列型の場合、各要素は値で初期化されます。
  • それ以外の場合、オブジェクトはゼロで初期化されます。

強調鉱山。したがって、intはクラスタイプでもないため、最後のルールに該当し、ゼロで初期化されるため、これは完全に正しい動作です。

于 2012-11-16T08:00:44.170 に答える