2011-03-07 8 views
9

C++ヘッダーファイルに静的グローバル変数がある場合、ヘッダーファイルを含む各変換単位は、変数の独自のコピーで終了します。インラインメンバー関数によって使用される静的グローバル変数

#include <iostream> 

static int n = 10; 

class Foo { 
public: 
    void print() { std::cout << n << std::endl; } 
}; 

:しかし、私は、同じヘッダファイル内のクラスを宣言し、そのクラスのメンバ関数を作成する場合、例えば、静的なグローバル変数を使用してクラス宣言内にインラインで実施

その後、私は、GCC 4.4の下で少し奇妙な行動を参照してください。

  1. 私は最適化せずにコンパイルした場合は、メンバ関数のすべての使用は、翻訳単位の1(G ++コマンドに言及した最初のものから、変数のコピーを使用しますライン)。

  2. -O2でコンパイルした場合、メンバー関数を使用するたびに、大文字小文字が変換された変換単位の変数のコピーが使用されます。

明らかにこれは本当に悪いデザインなので、この質問は好奇心から外れています。しかし、私の質問にもかかわらず、C + +の標準はこのケースについて何を言っているのですか?最適化を有効にした場合としなかった場合の動作を変えることでg ++が正しく動作しますか?

+1

可能な重複:[hファイルの静的キーワードと内部リンケージ](http://stackoverflow.com/questions/4276794/static-keyword-in-h-file-and-internal-linkage)。 –

答えて

12

標準(3.2/5)言う:

クラスタイプ(節9)の複数の定義 、 存在できは...定義が 次の要件を満たして... 。Dの各 定義で、名前に対応する、 はDの 定義内で定義されたエンティティを指すもの、又は 同じエンティティ

を指す、3.4に従ってルックアップ

コードが失われる場所です。 Fooの異なる定義におけるnの使用は、同じオブジェクトを参照していません。ゲームオーバー、未定義の動作、そうですね、gccはさまざまな最適化レベルでさまざまなことを行うことができます。

3.2/5が継続:オブジェクトはDの全 定義に同じ 一体または列挙型を持つ場合、名前は、内部または全く リンケージと CONSTオブジェクトを参照することができることを除いて

をその目的は 定数式(5.19)、その値で初期化(ただし アドレス)オブジェクトの使用され、そして オブジェクトがD

の全て 定義に同じ値を有しています

あなたのコード例では、nstatic const intにするとすべて美しいものになります。この節では、異なるTUが同じオブジェクトまたは異なるオブジェクトを参照しているかどうかに関係なく、それらが使用するものはすべてコンパイル時の定数値であり、すべて同じものを使用するという条件が記述されていることは偶然ではありません。

+1

+1:ODRが非常に微妙な方法で違反することがあります。 –

+0

優れた答えです。ありがとうございました。 – jchl

関連する問題