2014-11-05 16 views
3

如果我有魔法靜力學是否保證右側只執行一次?

atomic<int> cnt=0; 

int get_int() noexcept 
{ 
    cnt++; 
    return rand(); 
} 

然後:

void func() 
{ 
    static const auto value = get_int(); 
} 

我知道會有對value初始化無競爭狀態,但我不知道是否 get_int()將被調用一次,或在我的示例中cnt將爲1(而不是2,3,4或5)。

假設多個線程輸入func()get_int只有1個呼叫站點在func()

+0

如果擔心多個線程同時調用'func',我想你可以使用類似'std :: call_once([] {cnt ++;});' – chris 2014-11-05 14:50:38

+0

cnt只是一個例子,我其實很擔心泄漏因爲我真正的get_int函數實際上返回指向它分配的對象的指針。 – NoSenseEtAl 2014-11-05 14:57:57

回答

8

C++ 11保證不會有競爭條件N3797 - §6.7/ 4

的實現允許具有靜態或 線程執行其他塊範圍變量的早期初始化在允許實現靜態初始化名稱空間範圍(3.6.2)中的靜態或線程存儲持續時間變量的 的條件下存儲持續時間。否則,這種變量是 第一次控制通過它的聲明初始化;這樣的變量在初始化完成時被認爲初始化。如果通過拋出異常退出初始化,則初始化 未完成,因此下次控制進入聲明時將再次嘗試初始化。如果控制在變量初始化時同時輸入 聲明,則併發執行將等待 初始化完成.92如果控制器初始化時遞歸地重新輸入聲明,則變量爲 ,則行爲未定義。 [例:

int foo(int i) { 
    static int s = foo(2*i); // recursive call - undefined 
    return i+1; 
} 

- 結束例如]

這不是重入但是線程安全的。確保代碼的其他部分無論如何都會在func()之前調用get_int()

+0

§6.7中的第4段被引用爲「6.7/4」,或者更好的是使用節標籤「[stmt.dcl]/4」。標準號碼隨着標準的發展而變化,但標籤保持不變。 – Casey 2014-11-05 15:46:35

+0

@Casey謝謝,也爲格式。我之前正在摔跤報價標籤 – 2014-11-05 15:47:14

1

get_int()將從該行只被調用一次,但給定您的代碼,get_int()可以事先從代碼中的不同位置調用。