2011-09-24 1 views
5

私は、ヘッダー内のベクトルを持っているので、同様に:私はこれを持って関連するCPPファイルでグローバルベクトルは呼び出し間で自身を空にしますか?

extern std::vector<Foo> g_vector; 

std::vector<Foo> g_vector; 

私もクラスBarを持って、それのコンストラクタで、それが追加されますそのようなg_vectorにいくつかのもの、:

Bar::Bar(/* stuff */) 
{ 
    // do things 
    std::cout << g_vector.size() << std::endl; 
    g_vector.push_back(somefoo); 
    std::cout << g_vector.size() << std::endl; 
} 

私は正気のように、関数内Barを宣言した場合人、それは正常に動作するようです。しかし、関数の外にBarを宣言したい場合は、変なことが起こります。たとえば、私はBarをMyFile1.cppとMyFile2.cppに宣言していますが、Barの私のcoutステートメントのためにFooがベクターにプッシュされるのを見ることができますが、次のBarがそのコンストラクタを実行するとベクトルのサイズは0再び。言い換えれば、私の出力は

0 
1 
0 
1 

となりますか?ちょうど余分なダブルを確認するために、私は&g_vectorを実際に印刷して、実際にpush_backが正しいベクトルに入り、すべてのアドレスが一致していることを確認しました。それが価値あるものであれば、これらのものがベクターにどのような順序で入るかは関係ありません。私は初期化の順序などには関係しません。

+1

静的 'Bar'インスタンスの前に' g_vector 'が構築されると思われる理由はありますか? – Gabe

答えて

6

問題が本当にわかりませんが、次のパターンはそれを解決するのに役立ちます:グローバル変数へのアクセッサを定義し、それを静的関数変数として割り当てます。 CPPファイルで

std::vector<Foo> &getGlobalVector(); 

:ヘッダーファイルで

std::vector<Foo> &getGlobalVector() 
{ 
    static std::vector<Foo> s_vector; 
    return s_vector; 
} 

このパターンは、現代のC++設計でアンドレイアレキの "一般的なシングルトン" 実装からインスピレーションを得ています。

私は、既存のアプリケーションを維持しながら既存のグローバル変数に落ちたとき(またはまれに私が自分で使用することを選択したまれに)、このパターンを体系的に使用する習慣をとっています。上記のアプリケーションでは難しい再現性のバグのカップル。

これは実際には、複数の初期化または初期化の順序に関連する問題を回避するのに役立ちます。

6

グローバル値の初期化の順序は定義されていません。

static initialization fiascoについてはこちらをご覧ください。

関数にを宣言すると、g_vectorは、プログラムが実行される前に初期化されることが約束されているため、前に初期化されます。 Barがグローバル変数の場合、問題があります。

関連する問題