グローバル状態にはいくつかの可能性があります (変更可能かどうかに関係なく)。
初期化の問題が発生する恐れがある場合は、このlocal static
アプローチを使用してインスタンスを作成する必要があります。
あなたが提示する不格好なシングルトン設計は必須の設計ではないことに注意してください。
class Singleton
{
public:
static void DoSomething(int i)
{
Singleton& s = Instance();
// do something with i
}
private:
Singleton() {}
~Singleton() {}
static Singleton& Instance()
{
static Singleton S; // no dynamic allocation, it's unnecessary
return S;
}
};
// Invocation
Singleton::DoSomething(i);
もう 1 つのデザインは多少似ていますが、非グローバル デザインへの移行がはるかに簡単になるため、私はそれを好みます。
class Monoid
{
public:
Monoid()
{
static State S;
state = &s;
}
void doSomething(int i)
{
state->count += i;
}
private:
struct State
{
int count;
};
State* state;
};
// Use
Monoid m;
m.doSomething(1);
ここでの正味の利点は、状態の「グローバル性」が隠されていることです。これは、クライアントが心配する必要のない実装の詳細です。キャッシュに非常に便利です。
デザインについて質問させてください。
- 実際に特異点を強制する必要がありますか?
- 実際に開始前にオブジェクトを構築する必要があります
main
か?
特異点は一般的に過度に強調されています。ここでは C++0x が役に立ちますが、それでも、プログラマーの振る舞いに依存するのではなく、技術的に特異点を強制するのは非常に煩わしい場合があります。それぞれの間で構成を変更するだけですか?うーん。一度インスタンス化して、仲間のプログラマーを信頼する方がはるかに簡単です...または機能テスト;)
2 番目の質問は、機能よりも技術的なものです。プログラムのエントリ ポイントの前に構成が必要な場合は、開始時に単純に読み取ることができます。
素朴に聞こえるかもしれませんが、実際には、ライブラリのロード中の計算には 1 つの問題があります。それは、エラーをどのように処理するかということです。スローすると、ライブラリはロードされません。投げ続けないと無効状態。面白くないですよね?通常の制御フロー ロジックを使用できるため、実際の作業が開始されると、作業ははるかに単純になります。
そして、状態が有効かどうかをテストすることを考えているなら...なぜ、テストしたいポイントですべてを構築しないのですか?
最後に、非常に問題とglobal
なるのは、導入される隠れた依存関係です。実行の流れやリファクタリングの影響を推論するために依存関係が暗黙的に示されている場合は、はるかに優れています。
編集:
初期化順序の問題について: 単一の翻訳単位内のオブジェクトは、定義された順序で初期化されることが保証されています。
したがって、次のコードは標準に従って有効です。
static int foo() { return std::numeric_limits<int>::max() / 2; }
static int bar(int c) { return c*2; }
static int const x = foo();
static int const y = bar(x);
初期化順序は、別の翻訳単位で定義された定数/変数を参照する場合にのみ問題になります。そのため、同じ翻訳単位内のオブジェクトstatic
のみを参照する限り、オブジェクトは問題なく自然に表現できます。static
スペースの問題に関して:as-if
ルールはここで驚異的な効果を発揮します。非公式に言えば、このas-if
ルールは、動作を指定し、それがどのように提供されるかについて世界で気にせずに、コンパイラ/リンカー/ランタイムに任せて提供することを意味します。これにより、実際に最適化が可能になります。
したがって、コンパイラ チェーンが定数のアドレスが取得されないことを推論できる場合、定数を完全に除外する可能性があります。いくつかの定数が常に等しいと推測でき、それらのアドレスが決して検査されないことが再び推測できる場合、それらをマージすることができます。