2010-11-25 4 views
10

さらに別のstatic質問です。 私は次のことを読んだことがある:hファイル内の静的キーワードと内部リンケージ

そして、私はまだ、次の行動を理解することができない: 私は1つのhファイルがあります:

// StaticTest.h 
#include <stdio.h> 

static int counter = 0; 

struct A { 
    A() { 
     counter++; 
     printf("In A's ctor(%d)\n", counter); 
    } 
    ~A() { 
     counter--; 
     printf("In A's dtor(%d)\n", counter); 
    } 
}; 

static A a; 
を の

そして2 cppファイル:

// StaticTest1.cpp 
#include "StaticTest.h" 

int main() { 
return 0; 
} 

そして:

// StaticTest2.cpp 
#include "StaticTest.h" 

プログラムの出力は次のとおりです。

In A's ctor(1) 
In A's ctor(2) 
In A's dtor(1) 
In A's dtor(0) 

Aのコンストラクタはh以来、2回呼び出されファイルは2回含まれ、Aのインスタンスastaticと宣言されているため、内部リンケージがあり、コンパイラは満足しています。 counterも静的であると宣言されているため、内部リンケージもあり、2つのcppファイルで値が共有されないことが予想されますが、プログラム出力は値が2までカウントされることを意味します。

洞察?

EDIT: hcppファイル内の静的変数の宣言の文脈における「良いプログラミング習慣を」も歓迎されると考えられるものに関するすべての答え。

+0

*実装の詳細について何かを言うと、約コンパイル時に初期化実行時に初期化静的な値に対して静的な値を、私はそれを答えとして掲示することに自信を持っていません。 'counter'を初期化しないで' main() 'に初期化してみてください。 –

+0

@ Benoit Thiery:これは完全なソースコードです。 –

+0

@ Ignacio Vazquez-Abrams:MSDNのページから: "変数を宣言すると、変数には静的持続時間があり、別の値" –

答えて

9

StaticTest.hが差分ソースファイル間で共有される場合、未定義の動作が発生します。

異なる翻訳単位でクラスまたはインライン関数を定義する場合、それらの定義は同じ(トークンの同じシーケンス)でなければならず、重要な識別子は同じエンティティを参照する必要があります(const内部結合のオブジェクトを除く)別の翻訳単位の定義と同じです。

counterには内部リンケージが含まれているため、異なる翻訳単位では、関数定義の識別子が別のオブジェクトを参照しています。

参考:C++ 03 3.2 [basic.def.odr]/5.私が欲しい*

+1

+1 C++は難しい言語です:) –

+1

私はあなたの答えを完全に理解していません - 'counter'はクラス定義ではなく、変数宣言であり、とにかく、内部のリンケージ手段ではありません2つのエンティティを持ちます。それぞれのエンティティは独自の翻訳単位ですか? –

+3

@Itamar Katz:はい、あなたは 'counter 'という名前の複数のエンティティを持っていますが、それぞれが内部リンケージを持っていますが、あなたは' A'、 'A :: A'、' A ::〜 A'。あなたの定義は同じトークンシーケンス(良い)から成りますが、 'counter'は内部リンケージを持っているため、' A'の定義でその識別子を使用すると、別々の翻訳単位ごとに異なるオブジェクトを参照します。つまり、 'A'の定義はODRに違反する翻訳単位では同じではありません。 –

関連する問題