为什么C++11允许将局部变量声明为thread_local?

6
int main()
{
    thread_local int n;
}

在C++11中,上述代码是合法的。

根据cppreference的说法:

thread_local关键字只允许用于在命名空间作用域内声明的对象、块作用域内声明的对象和静态数据成员。

我只是想知道:

局部变量总是在当前线程的堆栈上,因此始终是线程本地的。在这种情况下,thread_local int n;int n;完全相同。

C++11为什么允许将局部变量声明为thread_local,而不是明确禁用它以避免滥用呢?


1
本地化并不意味着自动存储期。实际上,thread_local 为其定义了一个新的存储期,就像 static 一样。 - chris
当地化并不意味着自动存储持续时间。有什么例子吗? - xmllmx
1
void foo() { static int s; } - 假设 foo 被调用以创建 s,那么 s 不会在程序结束之前被销毁。它不会被放置在函数的栈帧中 - 这样会过早地销毁它。 thread_local 是一种替代 static 或隐式自动存储期的存储期方式。仅仅因为它是隐式的,并不意味着它总是那个 - 你可以明确并改变它,例如改为线程局部。我使用 static 是因为它更容易理解。你可以大部分上把 thread_local 看作类似的,只不过是每个线程而不是全局的。 - chris
2个回答

6
根据标准,块作用域下的thread_local变量也隐式地是static。然而,并不是所有的static变量都是thread_local
所以,
 int main()
 {
       thread_local int x;
 }

实际上等同于

 int main()
 {
       thread_local static int x;
 }

但不同于;

 int main()
 {
       int x;    //  auto implied
 }

2

你说得对,栈变量是线程本地的。

thread_local关键字仅适用于全局或静态作用域的变量。通常,在程序(或dll / so)加载时创建这些变量的单个实例。thread_local为每个线程创建这些全局变量的单独实例。

不将其设置为默认值的可能原因是这是C ++ 03中不存在的新行为。此外,根据ABI,访问thread_local变量可能需要调用内核,这很慢,因此只在真正需要时执行。


3
"栈变量"具有自动存储期。一个 thread_local 对象不能放在栈上,因为它的生命周期持续到线程终止。它更像是一个特定于线程的静态对象。 - molbdnilo
这将自动导致不同的线程有不同的实例。 - doron
1
thread_local 不仅涉及到有单独的实例,还涉及到对象的生命周期。 "具有线程存储期的变量在其第一次 odr-use 之前必须初始化,并且如果构造,则应在线程退出时销毁。"(§3.7.2); "当 thread_local 应用于块作用域变量时,如果未显式出现,则隐含使用 storage-class-specifier static。"(§7.1.1) - molbdnilo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接