4

ローカル データと関数を格納するために匿名の名前空間を使用しており、データがいつ初期化されるかを知りたいですか? アプリケーションが静的データと同じ方法で起動するときですか、それともコンパイラに依存しますか? 例えば:

// foo.cpp
#include "foo.h"

namespace {

const int SOME_VALUE = 42;

}

void foo::SomeFunc(int n)
{
    if (n == SOME_VALUE)
    {
        ...
    }
}

問題は、一部のコードをスレッドセーフにすることから生じます。SOME_VALUE上記の例では、 SomeFunc が初めて呼び出される前に が初期化されていることを確認する必要があります。

4

4 に答える 4

6

C++ 標準、3.6.2/1 :

ゼロ初期化と定数式による初期化をまとめて静的初期化と呼びます。他のすべての初期化は動的初期化です。定数式 (5.19) で初期化された静的ストレージ期間を持つ POD 型 (3.9) のオブジェクトは、動的初期化が行われる前に初期化されなければなりません。同じ翻訳単位の名前空間スコープで定義され、動的に初期化される静的ストレージ期間を持つオブジェクトは、それらの定義が翻訳単位に現れる順序で初期化されます。

これは事実上、別の翻訳単位が外部から SomeFunc 関数を呼び出した場合でも、 SOME_VALUE 定数は定数式で初期化されるため、常に正しく初期化されることを意味します。

関数を早期に (メインの前に) 呼び出す唯一の方法は、動的初期化でオブジェクトを初期化することです。しかし、その時までに、標準的な見積もりによると、POD 変数の初期化は既に完了しています。

于 2008-12-01T15:19:53.613 に答える
2

この特定のケース (const であるグローバル変数) では、変数はコンパイル時に「初期化」されます。

SOME_VALUE は常に 42 です。

実際、ほとんどの (すべての?) コンパイラは、ハードコードされているかのように実際にこれをコンパイルします。

void foo::SomeFunc(int n)
{
    if (n == 42)
    {
        ...
    }
}
于 2008-12-01T14:51:55.823 に答える
1

名前空間は、初期化の時間とは何の関係もありません。名前空間が行うことは、それに属する名前を変更することだけです。

于 2008-12-01T14:52:14.277 に答える
0

実際の質問に対する正しい答えについては、マシューの答えを参照してください。

ただし、匿名名前空間は、グローバルおよび/または静的オブジェクトの有効期間の開始と終了には影響しないことに注意してください。つまり、単純な古いグローバルを使用する場合と同じように、静的な初期化順序の問題に対して脆弱です。

このリンクには、次のトピックの「初回使用時の構築」を使用して、問題を回避するためのヒントもいくつかあります。

于 2008-12-01T14:52:05.167 に答える