これは、適切なケースが限られているため、少なくとも高品質のコードではまれにしか発生しません。これが基本的に行うことは、グローバル状態のジャストインタイム初期化です (いくつかのグローバル機能を提供するため)。この典型的な例は、最初の呼び出しでジェネレーターをシードする乱数ジェネレーター関数を持つことです。これのもう 1 つの典型的な用途は、最初の呼び出しで初期化されたシングルトンのインスタンスを返す関数です。しかし、他のユースケースの例はほとんどありません。
一般的に言えば、グローバルな状態は望ましくなく、自己完結型の状態を含むオブジェクトを持つことが推奨されます (モジュール性などのために)。しかし、グローバルな状態が必要な場合 (時には必要な場合もあります)、何らかの方法でそれを実装する必要があります。何らかの種類の重要なグローバル状態が必要な場合は、おそらくシングルトン クラスを使用する必要があります。そのアプリケーション全体の単一インスタンスを配信するための推奨される方法の 1 つは、初期化されたローカルの静的インスタンスへの参照を配信する関数を使用することです。最初の呼び出しで。必要なグローバル状態がもう少し些細な場合は、ローカルの static bool フラグを使用してスキームを実行することは、確かに受け入れられる方法です。つまり、その方法を採用しても根本的な問題はないと思います、しかし、そのようなコードが提示された場合、私は当然、その動機(グローバル状態を必要とする)に疑問を投げかけます。
グローバル データの場合は常にそうであるように、マルチスレッドは、このような単純化された実装でいくつかの問題を引き起こします。グローバル状態の単純な導入は、本質的にスレッドセーフになることは決してありません。このケースも例外ではなく、その特定の問題に対処するための対策を講じる必要があります。これが、グローバルな状態が望ましくない理由の一部です。
SomeClass::function への static bool init の動作は、非静的メンバー変数で実現できます。
同じ動作を実現する別の方法がある場合は、2 つの別の方法を技術的な問題 (スレッド セーフなど) で判断する必要があります。しかし、この場合、実装の詳細よりも必要な動作が疑わしいものであり、代替の実装が存在してもそれは変わりません。
次に、グローバル状態のジャストインタイム初期化を非静的データ メンバー (おそらく静的データ メンバー)に基づくものに置き換える方法がわかりません。できたとしても、それは無駄であり (プログラムごとに 1 回実行するためにオブジェクトごとのストレージが必要です)、その理由だけでは、より良い代替手段にはなりません。
可視性が void SomeClass::function() スコープに制限されているため、SomeClass の他の関数は static bool init 値をチェックできませんでした。
私は通常、それを「プロ」列に入れます(プロ/コンのように)。これは良いことです。これは情報の隠蔽またはカプセル化です。他の人が気にするべきではないことを隠すことができれば、それは素晴らしいことです! しかし、グローバル状態がすでに初期化されているかどうかを知る必要がある他の関数がある場合は、おそらくシングルトン クラスの行に沿って何かが必要になります。
静的変数は、オブジェクトの状態ではなくグローバルな状態を定義するため、オブジェクト指向ではありません。
OOPっぽいかどうか、誰が気にしますか?しかし、はい、ここで問題になるのはグローバルな状態です。初期化を実装するためにローカル静的変数を使用することはあまりありません。グローバル状態、特に変更可能なグローバル状態は、一般的に悪いものであり、決して悪用されるべきではありません。それらはモジュール性を妨げます (モジュールはグローバルな状態に依存する場合、モジュールの自己充足性が低下します)。それらは本質的に共有データであるため、マルチスレッドの問題を引き起こします。それらを使用するすべての関数を再入不可 (非純粋) にし、デバッグを行います。難しい、など... リストは続きます。しかし、これらの問題のほとんどは、実装方法とは関係ありません。一方、ローカル静的変数を使用することは、静的初期化順序の大失敗を解決するための良い方法です。そのため、(十分に正当化された) グローバル状態を導入するときに心配する問題が 1 つ少なくなります。あなたのコードに。