2017-02-09 76 views
3
int main() 
{ 
    thread_local int n; 
} 

上面的代码在C++ 11中是合法的。为什么C++ 11允许你声明一个局部变量为thread_local?

根据cppreference

thread_local关键字仅允许在 命名空间范围中,在框范围,以及静态数据成员 声明对象声明的对象。

我只是想知道:

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

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

+1

本地并不意味着自动存储时间。实际上,thread_local定义了一个新的存储持续时间,就像'static'一样。 – chris

+0

“本地化并不意味着自动存储时间。”,任何示例? – xmllmx

+1

'void foo(){static int s; }'''s'不会被销毁,直到程序结束时,假设调用了'foo'以便创建's'。它不会放在函数的堆栈框架上 - 那会太早摧毁它。 'thread_local'是'static'或者**隐式**自动持续时间的替代存储持续时间。仅仅因为它是隐式的并不意味着它总是那个 - 你可以明确地将其改变,例如,改为线程本地。我正在使用'static',因为它可能更加熟悉。你可以通过相同的方式来思考'thread_local',但是每个线程都可以代替全局。 – chris

回答

2

根据标准,块范围内的变量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 keywork仅适用于全局或静态范围的变量。通常,这些变量的单个实例是在程序(或dll/so)加载时创建的。 thread_local为每个线程分别创建这些全局变量的实例。

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

+1

“堆栈变量”具有自动存储持续时间。一个'thread_local'对象不能在堆栈上,因为它的生命周期一直持续到线程终止。它更像是一个特定于线程的静态对象。 – molbdnilo

+0

这会自动为不同的线程产生不同的实例。 – doron

+1

'thread_local'不仅是关于存在单独的实例,还关于对象的生命周期。 “具有线程存储持续时间的变量应在其第一次使用odr之前初始化,如果构造, 应在线程退出时销毁。” (§3.7.2); “当'thread_local'被应用到一个块范围的变量时,如果它没有明确显示,那么隐含* storage-class-specifier *'static'。 (第7.1.1节) – molbdnilo

相关问题