しかし、C++11 標準について読んだところによると、グローバル オブジェクトを として宣言してもthread_local
、オブジェクト自体は、プログラムの実行中に作成できるすべての可能なスレッドに対して 1 回インスタンス化されます。
これは、C++11 標準の状態ではありません。C++11 標準 (ドラフト n3337) の関連セクション:
キーワードで宣言されたすべての変数には、thread_local
スレッド保存期間があります。これらのエンティティのストレージは、それらが作成されたスレッドの間持続します。スレッドごとに個別のオブジェクトまたは参照があり、宣言された名前の使用は、現在のスレッドに関連付けられたエンティティを参照します。
- 7.1.1 ストレージ クラス指定子、第 4 節:
thread_local
指定子は、名前付きエンティティにスレッド ストレージ期間 (3.7.2) があることを示します。これは、名前空間またはブロック スコープの変数の名前と、静的データ メンバーの名前にのみ適用されます。 thread_local がブロック スコープの変数に適用されると、明示的に表示されない場合、storage-class-specifier static が暗示されます。
thread_local
オブジェクトがグローバル名前空間で定義されている場合、そのオブジェクトの単一のインスタンスのみが作成されるとはどこにも述べていません。Jesse Goodによって既に投稿された別の例では、グローバル オブジェクトの各インスタンスの一意のアドレスが出力されます (オンライン デモを参照)。
#include <iostream>
#include <thread>
#include <vector>
struct S {};
thread_local S global_s;
int main()
{
std::vector<std::thread> threads;
for (int i = 0; i < 10; ++i)
threads.push_back(std::thread([](){ std::cout << &global_s << '\n'; }));
for (auto& t: threads) t.join();
}
出力:
0x4165993f
0x4205a93f
0x4485e93f
0x42a5b93f
0x4525f93f
0x45c6093f
0x4666193f
0x4706293f
0x43e5d93f
0x4345c93f