web-dev-qa-db-ja.com

ローカルの静的変数の初期化はC ++ 11でスレッドセーフですか?

これはよくある質問であることがわかっていますが、非常に多くのバリエーションがあるので、改めて説明し、できれば現在の状態を反映した回答をお願いします。何かのようなもの

Logger& g_logger() {
    static Logger lg;
    return lg;
}

変数lgのコンストラクターは一度だけ実行されることが保証されていますか?

以前の回答から、C++ 03ではこれはそうではないことを知っています。 C++ 0xドラフトでは、これが強制されます。しかし、私はより明確な答えが欲しい

  1. C++ 11標準(ドラフトではありません)で、スレッドセーフな初期化動作は確定していますか?
  2. 上記がイエスの場合、人気のあるコンパイラの最新リリース、すなわちgcc 4.7、vc 2011およびclang 3.0では、それらは適切に実装されていますか?
192
Ralph Zhang

関連セクション6.7:

そのような変数は、コントロールがその宣言を初めて通過するときに初期化されます。このような変数は、初期化が完了すると初期化されたと見なされます。 [...]変数の初期化中に制御が同時に宣言に入る場合、同時実行は初期化の完了を待機します。

次に、脚注があります。

実装は、初期化子の実行にデッドロックを導入してはなりません。

はい、あなたは安全です。

(これは、参照を介した変数へのその後のアクセスについてはもちろん何も言いません。)

172
Kerrek SB

--fno-threadsafe-staticsも言及する価値があります。 gccの場合:

C++ ABIで指定されたルーチンを使用してローカルスタティックのスレッドセーフな初期化を行うために、余分なコードを発行しないでください。このオプションを使用すると、スレッドセーフである必要のないコードでコードサイズをわずかに削減できます。

また、古いスレッドを見てください GCCで関数の静的変数はスレッドセーフですか?

15
Denis Glotov