私はVisual Studio 2013を使用していますが、 "静的静的"機能はまだ実装されていません。スレッドセーフです。だから、代わりにローカル静的std :: once_flagとローカル静的ポインタを使用した静的変数のスレッドセーフ初期化
Foo& GetInstance()
{
static Foo foo;
return foo;
}
の私はこのような何か:
std::unique_ptr<Foo> gp_foo;
std::once_flag g_flag;
Foo& GetInstance()
{
std::call_once(g_flag, [](){ gp_foo = std::make_unique<Foo>(); });
return *gp_foo;
}
をしかし、私はgp_foo
とg_flag
グローバル変数(最初に、静的の初期化の順序に問題があるのアイデアを好きではありません変数を異なる翻訳単位に変換する;第2に、必要なときに、つまりGetInstance()に最初に呼び出した後にのみ変数を初期化したいので、次のコードを実装しました。
Foo& GetInstance()
{
// I replaced a smart pointer
// with a raw one just to be more "safe"
// not sure such replacing is really needed
static Foo *p_foo = nullptr;
static std::once_flag flag;
std::call_once(flag, [](){ p_foo = new Foo; });
return *p_foo;
}
これは動作しているようです(少なくともテストに合格したようです)が、スレッドセーフであるかどうかはわかりません。なぜなら、複数のスレッドで静的ローカル変数p_foo
とflag
の初期化に同じ潜在的な問題があるからです。 nullptr
の生ポインタの初期化とstd::once_flag
の初期化は、Foo
のコンストラクタを呼び出すより無邪気なようですが、本当に安全かどうかを知りたいと思います。
最後のコードスニペットに問題はありますか?
httpsを返すことを示唆している://codereview.stackexchangeを。 com/ – Blacktempel
[call_once on cppreference](http://en.cppreference.com/w/cpp/thread/call_once)を参照してください。特に箇条書きのポイント2 – Simple
@Simple _グループ内の呼び出しは、上記の選択された関数の実行が正常に完了する前に戻りません。つまり、例外を介して終了しません._しかし、懸念事項はstd ::に関するものではありません。 call_onceではなく、これらの2行について 'static Foo * p_foo = nullptr; std :: once_flagフラグ; ' – undermind