C ++で静的なクラス変数を初期化する必要があるのはなぜですか?

CおよびC ++では、すべての静的変数はデフォルトでゼロに初期化されます。

これは静的クラスのデータメンバーの場合ではありません。何故ですか?

#include 
using namespace std;

int var;

class MyClass
{
public:
    static int classVar;
};
int MyClass::classVar = 0; //Why I have to init it here?

int main(void)
{
    cout << ::var << endl;         //this is initalized to ZERO by default
    static int var;
    cout << var << endl;           //and this also is initalized to Zero
    cout << MyClass::classVar << endl;

    return 0;
}
13
@AlessandroPezzato:実際には、標準では、動的初期化を実行する前に、すべてのグローバル変数のメモリをゼロにすることについて明示しています。リテラル値が影響を受ける組み込み関数以外は、直接影響を受ける可能性があります - ルールの場合)観測できないからです。
追加された 著者 Matthieu M.,
var が0に初期化されているかわからない場合があります。
追加された 著者 Alessandro Pezzato,

3 答え

クラススコープでは、

int MyClass::classVar = 0; //Why I have to init it here?

定義であり、

static int classVar;

宣言、つまり変数はどこかで定義されることを約束します:宣言する変数を一度定義する必要があります。

その根拠は、クラス宣言が複数のソースファイルに含まれる可能性が高いということです。その一部が定義であるかどうかは、何度も繰り返されます:これは誤りです(例外はインライン[メンバ]関数です)。

値の初期化ルールによれば、

int MyClass::classVar; //Zero-initialized !

定義として。

namespaceスコープで宣言された変数も( extern 修飾されていない限り)定義です。

int var;

宣言と定義です:これをヘッダーに入れて複数の翻訳単位に含めると、エラー(「複数定義されたシンボル」など)が表示されます。

[Cではなく(Cではなく) var const の場合、自動的に static 1つの定義ルールに違反することは、それを複数のヘッダに入れるべきです。これはトピックから少し外れていますが、詳細を聞いてみてください]

23
追加された
@アレクサンドルC:それがなぜ必要なのか説明してもいいと思う。
追加された 著者 Nawaz,
ありがとう....本当に私はこのトピックを理解するのに役立ちます:)
追加された 著者 Muhammad Hewedy,
"int var の場合、ヘッダーにこれを入れて複数の翻訳単位に含めるとエラーが発生します("複数定義されたシンボル "など)。 **しかし、#ifndef ... #define ... #endifガードはこの問題を避ける(間違っていると言っているのではなく、確かに確認したい)
追加された 著者 pokche,
私はそれが尋ねられているのか分からない。 "なぜ = 0; を置く必要があるのですか?"
追加された 著者 Mat,
したがって、ゼロ初期化だけが必要な場合は、 int MyClass :: classVar; で十分です。それを試みたことはありませんが、Stdと削除された回答によれば、実際にはそれがあります。
追加された 著者 zerm,
"= 0"は必須ではありません。これがなくても、ゼロに初期化されます。
追加された 著者 rakesh,

C ++のよくある質問10.12では、

静的データメンバーは、コンパイル単位で明示的に定義する必要があります。

C ++ FAQよりhttp://www.parashift.com/c++- faq-lite/ctors.html#faq-10.12

それはあなたの質問に答えるか、C ++標準自体を参照したのですか?

6
追加された

コンパイラにその値が何であるかを伝える必要があるため、静的クラスのデータ変数を初期化する必要があります。クラスはデフォルト値の概念を持つ必要はありません。

変数型は、 string ""などに対して、 double 0.0の場合、0である int 、クラスは必ずしもデフォルト値を持つとは限りません。たとえば、 class Rectangle などを考えてみましょう。ゼロ値とは何か - 正方形のゼロの長方形または単位の長さの長方形ですか?静的変数の場合、すべてのデータ型をデフォルト値で初期化できるわけではないので、コンパイラは自分自身を定義するように要求します。

2
追加された
私はあなたがここで間違っていると思う:何もあなたが静的変数を定義し、それを初期化しないことを妨げるものはない。変数がクラスのインスタンスである場合、そのコンストラクタが呼び出されます。
追加された 著者 qdii,
@victorはい、そうです、それを私に気付いてくれてありがとう。問題は、初期化ではなく静的変数の定義についてでした。
追加された 著者 Pavlo Dyban,
静的変数を定義する必要があります。コンストラクターは初期化しません。以下の例を考えてみましょう... "int test :: k;"コメントはコンパイルされません。クラステスト{public:static int k; }; int test :: k; int main(){テストt; cout << t.k; 0を返します。 }
追加された 著者 rakesh,