2017-02-09 75 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

相關問題