[英]Allowed compiler optimizations on loops in C++11
是否允許符合C ++ 11的編譯器優化/轉換此代碼:
bool x = true; // *not* an atomic type, but suppose bool can be read/written atomically
/*...*/
{
while (x); // spins until another thread changes the value of x
}
等同於無限循環的任何東西:
{
while (true); // infinite loop
}
從單線程程序的角度來看,上述轉換肯定是有效的,但這不是一般情況。
此外,在C ++ 11之前是否允許優化?
絕對。
由於x
未標記為volatile
並且似乎是具有自動存儲持續時間和內部鏈接的本地對象,並且程序不對其進行修改,因此這兩個程序是等效的。
在C ++ 03和C ++ 11中,這是按照as-if規則,因為訪問非易失性對象不被認為是程序的“副作用”:
[C++11: 1.9/12]:
訪問由volatile glvalue(3.10)指定的對象,修改對象,調用庫I / O函數或調用執行任何這些操作的函數都是副作用,這是執行環境狀態的變化。 表達式(或子表達式)的評估通常包括值計算(包括確定用於glvalue評估的對象的身份以及獲取先前分配給用於prvalue評估的對象的值)和啟動副作用。 當對庫I / O函數的調用返回或對volatile對象的訪問進行評估時,即使調用隱含的某些外部操作(例如I / O本身)或易失性訪問,也會認為副作用已完成可能尚未完成。
C ++ 11確實為全局對象騰出空間,使其在一個線程中更改其值,然后在另一個線程中讀取新值:
[C++11: 1.10/3]:
特定點處線程T
可見的對象的值是對象的初始值,由T
分配給對象的值 , 或者由對象分配給對象的值另一個線程 ,根據以下規則。
但是,如果你這樣做,因為你的對象不是原子的:
[C++11: 1.10/21]:
程序的執行包含數據競爭,如果它在不同的線程中包含兩個沖突的動作,其中至少有一個不是原子的,並且都不會發生在另一個之前。 任何此類數據爭用都會導致未定義的行為。
並且,當調用未定義的行為時, 任何事情都可能發生 。
[C++11: 1.10/25]:
實現應該確保原子或同步操作分配的最后一個值(按修改順序)在有限的時間內對所有其他線程可見。
再次注意,對象必須是原子的 (例如, std::atomic<bool>
)才能獲得此保證。
允許編譯器對這兩個循環做任何事情。 包括終止程序。 因為無限循環具有未定義的行為,如果它們不執行類似同步的操作(執行需要與另一個線程或I / O同步的事情),根據C ++內存模型 :
請注意,這意味着具有無限遞歸或無限循環的程序(無論是作為for語句實現還是通過循環goto或其他方式)具有未定義的行為。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.