-2

コード:

#include <iostream>

class cMapRender
{
public:
unsigned int m_rightMargin;
unsigned int m_bottomMargin;
unsigned int m_x;
unsigned int test;
unsigned int m_y;
unsigned int m_width;
unsigned int m_height;
};

int main(int argc, char **argv)
{
cMapRender mapRender;

std::cout << mapRender.m_x << std::endl; //gives random values (like 45321231)
std::cout << mapRender.m_height << std::endl;
std::cout << mapRender.m_width << std::endl;

return 0;
}

デバッガーで実行すると (またはいくつかの値を計算するだけで)、一部のメンバーが 0 で、一部がランダムな値になる可能性はありますか? ポッド メンバーは 0 で初期化する必要があると思います。

Linuxでg ++ 4.7を使用しています。ideone.com で実行したとき、gcc 4.7 でもこのバグが発生しました。しかし、ideone.com gcc 4.3 では、すべてのメンバーが 0 で初期化されていました!

ここで何が起こっているのですか?メンバーが常に 0 で初期化されないのはなぜですか? C標準では、ポッドは常に0で初期化する必要があると書かれていることを読みました。

4

3 に答える 3

2

場合によります:

標準語

8.5. 初期化子 [dcl.init] / 11 .

オブジェクトに初期化子が指定されていない場合、オブジェクトはデフォルトで初期化されます。初期化が実行されない場合、自動または動的ストレージ期間を持つオブジェクトの値は不確定です。[注:静的またはスレッド ストレージ期間を持つオブジェクトはゼロで初期化されます。3.6.2 を参照してください。—エンドノート]

および (読みやすくするために順序を逆にします):

8.5. 初期化子 [dcl.init] / 6 .

タイプ T のオブジェクトをデフォルトで初期化するとは、次のことを意味します。

— T が (おそらく cv 修飾された) クラス型 (第 9 節) である場合、T のデフォルト コンストラクターが呼び出されます (T にアクセス可能なデフォルト コンストラクターがない場合、初期化の形式は正しくありません)。

— T が配列型の場合、各要素はデフォルトで初期化されます。

それ以外の場合、初期化は実行されません。 [鉱山を強調]

プログラムが const 修飾された型 T のオブジェクトの既定の初期化を呼び出す場合、T は、ユーザー提供の既定のコンストラクターを持つクラス型でなければなりません。

それらはデフォルトで初期化されています。intまたはのような組み込み型の場合double、その値は構造体が宣言されている場所によって異なります(経験則として (ただし、それと同じです):初期化されない限り、それらは常にガベージであると仮定します)

グローバル スコープまたはstaticストレージを使用する場合、それらはすべてゼロです (構造体がグローバル スコープにある構造体のメンバーである場合を含む)。

関数ローカル スコープでは、それらはガベージでいっぱいです。

例:

#include <iostream>

struct Foo {
    int x;
    int y;
};

Foo foo;

int main () {
    Foo bar;

    std::cout << foo.x << ":" << foo.y << '\n';
    std::cout << bar.x << ":" << bar.y << '\n';
}

これは最初の実行で私に与えます

0:0
-1077978680:12574708

再コンパイルせずに 2 回目の実行を行うと、次のようになります。

0:0
-1075556168:12574708

POD 構造体は、egmemsetまたは ...を使用してすべてゼロに初期化できます。

Foo foo = {0}; // C and C++03
Foo foo{0}; // C++11

ついに

あなたのコードは、それらのメンバーのゼロ初期化に依存しているとコメントしました。これは、コンストラクターが必要な場所です。

class cMapRender
{
public:
    unsigned int m_rightMargin;
    unsigned int m_bottomMargin;
    unsigned int m_x;
    unsigned int test;
    unsigned int m_y;
    unsigned int m_width;
    unsigned int m_height;

    cMapRender() :
       m_rightMargin(0),
       m_bottomMargin(0),
       /* and so forth */
    {}
};

クラスの設計上の問題 (いくつかの変数を -type にグループ化することをお勧めします) とは別に、これで問題Rectangleが解決します。


(注:この回答は、私が別の回答からコピーおよび変更したものです(C++で構造体のメンバー変数を初期化しています))

于 2013-06-24T13:18:00.910 に答える
1

言語規則によると、データ メンバーは初期化されていません。次のように値を初期化できます。

cMapRender mapRender{}; // C++11

また

cMapRender mapRender1 = {};           // C++03 and C++11
cMapRender mapRender2 = cMapRender(); // C++03 and C++11

これにより、データ メンバーの値が初期化されます。つまり0、この場合は初期化されます。

于 2013-06-24T13:16:33.440 に答える