2017-06-27 72 views
4

引用static_cast的引用與指向static_cast的指針具有相同的運行時開銷嗎?對引用static_cast的引用的成本以及指向指針的指針static_cast

E.g.

class B; 
class A: public class B; 

A obj; 
A& ref = obj; 
A* ptr = &obj; 

// 1 
static_cast<B&>(ref); 
// 2 
static_cast<B*>(ptr); 
+12

如果你開始擔心這一點,那麼你已經遠遠走幾步就到你的*過早的優化*。專注於製作好的,可讀的,有據可查的,可調整的代碼和工作代碼。然後你測試你的應用程序,如果它沒有達到可能的性能要求(並且記住「足夠好」通常足夠好),那麼你測量,分析和基準找到熱點和瓶頸,並且只把注意力集中在那些人身上,記住要記錄下這些。 –

回答

3

不,他們並不總是有相同的成本。隨着優化開啓,它們總是具有相同的成本或幾乎相同的成本。

如果您是鑄造向上或向下的繼承層次結構中,無論是

  • 多重繼承參與,或
  • 多態類從非多態類繼承,

然後指針的static_cast可能會產生conditional move指令的成本,而參考的static_cast則不會。

這是因爲在這些情況下,基類子對象可能沒有與其完整對象相同的地址,因此static_cast可能涉及應用偏移量:將源類型對象的地址添加到常量或從中減去常量計算目標類型對象的地址。

指針可以爲空,並且空指針的static_cast必須產生一個空指針,所以如果指針爲null,那麼偏移量將不會被應用。這意味着編譯器必須使用條件移動指令來根據指針是否爲空來選擇是否應用偏移量。

參考文獻不能爲空,因此參考的static_cast不需要進行條件移動。另外this指針是免疫的,因爲this指針永遠不能爲空。

請注意,這也會影響隱式派生到基值的轉換,而不僅僅是明確的static_cast

通常可以忽略條件移動的成本。如果代碼更易讀或使用指針表達,則使用指針。爲了避免有條件的移動而損害你的代碼幾乎總是非常愚蠢的。


例子:

struct A { int a; }; 
struct B { int b; }; 
struct C : A, B { int c; }; 

B* cast(C* ptr) { return ptr; } 
B& cast(C& ref) { return ref; } 

編譯器輸出:(與-O2最新GCC)

cast(C*): 
     leaq 4(%rdi), %rax 
     testq %rdi, %rdi 
     movl $0, %edx 
     cmove %rdx, %rax 
     ret 
cast(C&): 
     leaq 4(%rdi), %rax 
     ret 
1

它的確如此 - 您可以放心地假設在這兩種情況下的成本爲零。結果彙編中的static_cast唯一跟蹤(用MSVC++測試)是一個額外的指針副本,甚至可以在啓用任何優化的情況下對其進行優化。

+0

它取決於對象層次結構,在多繼承的情況下可能需要一些運行時指針算術 – Motti