考虑以下C ++ 11程序:
struct S {
S() {/* do something */ }
} global_object;
int main() {
}
我还没有GCC 4.8
进行测试,但是从我读到的关于C ++ 11标准的内容来看,无论我将全局对象声明为thread_local
,对象本身都将是为程序执行期间可以创建的所有可能线程实例化一次。
GCC中是否存在一种方法(可移植或不可移植),每次一个线程启动时都会实例化并构造全局对象,并且每次相同的线程完成时都会被破坏?
答案 0 :(得分:4)
但是从我读到的关于C ++ 11标准的内容来看,无论我将全局对象声明为
thread_local
,对象本身都将为可以创建的所有可能线程实例化一次在执行程序期间。
这不是C ++ 11标准所规定的。 C ++ 11标准(草案n3337)的相关章节:
使用
thread_local
关键字声明的所有变量都具有线程存储持续时间。这些实体的存储应持续创建它们的线程的持续时间。 每个线程有一个不同的对象或引用,并且声明的名称的使用是指与当前线程关联的实体。
thread_local
说明符表示命名实体具有线程存储持续时间(3.7.2)。 它只应用于命名空间或块作用域的变量名称以及静态数据成员的名称。当thread_local应用于块作用域的变量时,隐含存储类指定符静态如果它没有明确显示。
如果在全局命名空间中使用thread_local
定义了一个对象,则只会创建一个实例。由Jesse Good发布的替代示例打印全局对象的每个实例的唯一地址(请参阅online demo):
#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
答案 1 :(得分: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