2016-02-26 33 views
4

是否允許刪除未使用的方法的C++編譯器或鏈接器(通過任何C++標準)? 編譯器似乎被允許刪除未使用的靜態函數,允許連接器刪除未使用的函數。但是我沒有發現任何信息類的方法。當這個方法是虛擬的時候,這真的很有趣。C++編譯器/鏈接器是否允許刪除未使用的方法?

+0

未使用的'private'方法可能可以安全地刪除。 – axiac

+1

@DevSolar:如果方法真的沒有使用,我不明白這會對你產生什麼影響。唯一的兩種情況是在調試器中,如果你用vtable手動破解(你不應該這樣做)。 –

+0

@JørgenFogh:我主要指的是「當方法是虛擬的時候,這變得非常有趣」,這似乎意味着一個概念,可能會有一個未明確提及的方式涉及破壞。如果你喜歡,可以提供「問題氣味」。 ;-) – DevSolar

回答

1

C++標準在更抽象的層面上工作。它不需要C++實現實際上由像編譯器和鏈接器這樣的單獨工具組成。

順便說一句,我只是尋找我的機器上的draft PDF,並且只有一個整個1368的頁面文件中的單詞「接頭」,甚至認爲一個實例僅僅是在約22頁腳註字符集。

這個標準實際上講的是所謂的「as-if」規則

援引§1.9:

(...)符合實現需要模擬(僅) 觀察到抽象機的行爲如下面所解釋。

在爲這句話,腳註,它進一步說:

這一規定有時被稱爲「爲假設」規則,因爲 實現可以自由地忽略此 國際的任何要求標準,只要結果就好像 已經服從一樣,就可以從程序的可觀測的 行爲中確定。

如果某個函數沒有以任何方式在程序中的任何地方使用,那麼它不會對可觀察行爲產生任何影響。單獨的「as-if」規則使得編譯器或鏈接器完全可以將其從可執行結果中移除。

5

是的。

如果該方法未被使用,那麼就沒有辦法告訴它已被刪除 - 所以鏈接器可以這樣做。請注意,獲取方法的地址可能會被視爲「使用」方法 - 不僅僅是實際調用方法。

鏈接器很可能會刪除非虛擬成員函數(這很容易,節省空間)。

他們可以刪除未使用的虛函數,但是編譯器必須添加很多關於它的虛函數它調用,以便鏈接可以刪除未使用的(也可能是小型的虛函數表)的信息。在實踐中,我不認爲連接器是這樣做的,因爲增益可能很小,而且開發工作量需要相當大。

+1

如果能夠創建一個庫,那麼如果這通常是真的,你會如何?圖書館主要由未使用的功能組成。 – tofro

+2

庫(靜態庫)不是由鏈接器創建的。對於共享庫,所有公共符號在導出時都是「使用」的。 –

1

類方法在類定義中定義時會內聯。當它們分別實現時,它們是簡單函數,具有隱藏的第一個參數this,它成爲指向調用此函數作爲其類的成員的實例的指針。刪除未使用的類方法沒有問題。

編譯器可以檢查如何使用實例來檢測未使用的虛擬成員,但這樣做的好處很多。幾年前,GCC沒有這樣做。

關鍵字volatile或導出保存變量&函數/類方法從刪除優化。

2

由於C++標準對此沒有提及,所以說它可能更準確的說它不會阻止刪除未使用的成員函數,而不是說它允許它們被刪除。但同樣有效的說,它不需要將其刪除。順便說一句,所有功能都是如此。

如果構建鏈(編譯器,鏈接器等)中的程序可以檢測到任何符號(例如靜態或非靜態成員函數)未被使用,則它可以安全地刪除它們。

難度較大的實際問題可能是檢測到非靜態成員函數未被調用。更甚的是,如果它是虛擬的,因爲對象的靜態類型是決定調用虛擬函數的哪個重寫。原則上檢測這種情況並非不可能,但需要進行相當數量的分析。最終它會歸結爲構建鏈的實施質量,因爲該標準沒有特別要求。這取決於供應商是否選擇實施這種優化。而且,由於這不是許多開發者實際尋求的行爲(最有可能的人會尋求它會有一個過早的優化迷信)並不是很多。

相關問題