2012-10-18 46 views
6

當完全禁用優化時編譯同一段代碼(g++ -O0),然後再次啓用優化時(g++ -O3),如何更改源代碼本身的邏輯?編譯器優化如何影響代碼邏輯?

例如,編譯器可以

這兩個優化使代碼執行更快,而不影響原始源代碼的完整性。沒有這些優化的任何代碼都會在啓用它們的情況下運行。

但是,編譯器優化也會影響代碼邏輯。這裏有兩個例子,我知道:

我很驚訝和幸運,瞭解這些,因爲他們可能成爲錯誤情況下的巨大潛在問題。

所以我想知道,有沒有其他情況下,C++編譯器優化會影響代碼邏輯?我特別在g ++編譯器下尋找關於C++ 11的信息(沒有任何未定義的行爲),但是歡迎其他編譯器的提示。

+3

不要忘記提及未定義的行爲將意味着什麼。 – Mysticial

+0

我相信編譯器也可以'不計算'以後從不使用的東西。雖然這不會改變代碼的邏輯,但如果您要衡量性能,那可能會很糟糕。雖然我不確定。 – leo

+0

@leo好點!雖然,我總是期望編譯優化會更快,因爲這是優化器的工作。 – Ryan

回答

8

的「爲假設」規則:

實現是免費的,只要結果是,如果要求 已經服從無視這個 國際標準的任何要求,就這可以從程序的可觀察的 行爲中確定。例如,實際執行需求 不評估表達式的一部分,如果它可以推斷出它的值不是 未使用,並且沒有副作用影響程序的可觀察行爲 產生。

然而,標準提到這是允許一個優化,它打破了「爲假設」規則:

當滿足一定的條件,的實現,則允許省略 副本/移動類對象的構造,即使對象的構造函數和/或析構函數具有副作用。在 這樣的情況下,實現將被省略的複製/移動操作的源和目標視爲簡單地將 引用到同一對象的兩種不同方式,並且該對象的銷燬發生在 後面的時間如果沒有優化,兩個對象將被銷燬 。123複製/移動操作的此省音, 稱爲複製省略,允許在下列情況下 (其可以被組合以消除多個副本):

- 在返回 語句中的函數與一類返回類型,當表達式 是與 函數返回類型具有相同cvun資格類型的非易失性自動對象(函數 或catch-clause參數除外)的名稱時,可以通過構建 構造忽略複製/移動操作自動對象直接進入函數的返回值 值

- 如果操作數是 非易失性自動對象(函數或catch-clause 參數除外)的名稱,該作用域的作用域範圍未超出最內層 的末端,並將try-block 當臨時類對象,其具有 - (如果存在的話),從 操作數到異常對象(15.1)複製/移動操作可以通過 直接構建自動對象到異常對象

省略沒有被綁定到參考 (12.2)將被複制/移動到類型對象與相同的 cv-unqualified類型,複製/移動操作可以省略 直接構建臨時對象到 省略副本的目標/移動

- 當異常 處理程序(第15)的異常聲明聲明同一類型的對象(除了 CV-資質)作爲異常對象(15.1),如果程序的含義爲 ,除了執行構造函數和析構函數之外,可以通過將異常聲明視爲 異常對象的別名來省略複製/移動操作 由異常聲明聲明的對象。

1

「未指定行爲」是行爲,其中實現可以自由選擇任何可能的行爲。在這種情況下,優化器可能會影響所作的選擇。

一個簡單的例子是函數參數的評估順序。非優化構建可以使用從左到右或從右到左,而優化構建可以以「混合」順序評估參數。一個很好的理由是在參數中最大化共同子表達式優化的機會。

如果這些參數中的任何一個具有明顯的副作用,那麼代碼邏輯將被改變,但是否這是一個錯誤因案例而異。