0

次の C++11 プログラムを検討してください。

struct S {
   S() {/* do something */ }
} global_object;

int main() {
}

まだテストする必要はありませんがGCC 4.8、C++11 標準について読んだところによると、グローバル オブジェクトを として宣言してもthread_local、オブジェクト自体は、実行中に作成できるすべての可能なスレッドに対して 1 回インスタンス化されます。プログラムの実行。

GCC で、1 つのスレッドが開始するたびにグローバル オブジェクトをインスタンス化して構築し、同じスレッドが終了するたびに破棄する方法 (移植可能かどうか) はありますか?

4

2 に答える 2

4

しかし、C++11 標準について読んだところによると、グローバル オブジェクトを として宣言してもthread_local、オブジェクト自体は、プログラムの実行中に作成できるすべての可能なスレッドに対して 1 回インスタンス化されます。

これは、C++11 標準の状態ではありません。C++11 標準 (ドラフト n3337) の関連セクション:

  • 3.7.2 スレッド保存期間、節 1:

キーワードで宣言されたすべての変数には、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
于 2013-07-04T14:17:57.037 に答える
3

グローバル オブジェクトを thread_local として宣言しても問題ありません

試してみましたか?スレッドごとに個別のインスタンス作成されると確信しています。

coliruで次のコードを参照してください。

struct S {
   int i = 0;
   S() {}
};

thread_local S global;

int main()
{
    std::thread t1([](){global.i = 1; std::cout << global.i << std::endl;});
    t1.join();
    std::cout << global.i << std::endl;
    std::thread t2([](){global.i = 2; std::cout << global.i << std::endl;});
    t2.join();
    std::cout << global.i << std::endl;
    std::thread t3([](){global.i = 3; std::cout << global.i << std::endl;});
    t3.join();
    std::cout << global.i << std::endl;
}

以下を出力します。

1
0
2
0
3
0
于 2013-07-04T13:42:19.987 に答える