2012-09-25 67 views
1

請注意以下代碼。據我所知,dynamic_cast比static_cast慢。因爲它在運行時評估類型。 我的疑問是,如果我們使用typeid()的static_cast作爲下面,它將需要相同的時間作爲動態演員? 它會比dynamic_cast更快嗎?static_cast和RTTI vs dynamic_cast

class Shape 
{ 
public: 
    virtual ~Shape(){} 
}; 
class Circle : public Shape{ }; 
class Square : public Shape{ }; 

靜態鑄造用RTTI:

Circle c; 
Shape* s = &c; // Upcast: normal and OK 

// More explicit but unnecessary: 
s = static_cast<Shape*>(&c); 
// (Since upcasting is such a safe and common 
// operation, the cast becomes cluttering) 

Circle* cp = 0; 
Square* sp = 0; 

// Static Navigation of class hierarchies 
// requires extra type information: 
if(typeid(s) == typeid(cp)) // C++ RTTI 
    cp = static_cast<Circle*>(s); 
if(typeid(s) == typeid(sp)) 
    sp = static_cast<Square*>(s); 
if(cp != 0) 
    cout << "It's a circle!" << endl; 
if(sp != 0) 
    cout << "It's a square!" << endl; 

動態轉換:

Circle c; 
Shape* s = &c; // Upcast: normal and OK 

s = &c; 
Circle* cp = 0; 
Square* sp = 0; 
cp = dynamic_cast<Circle*>(s); 
    if(cp != 0) 
    cout << "It's a circle!" << endl; 
sp = dynamic_cast<Square*>(s); 
if(sp != 0) 
    cout << "It's a square!" << endl; 
+0

這隻有在你引用指向對象的指針時纔有效。只有這樣''typeid'才能與動態類型的對象一起工作,而不是隻給你'Circle *'和'Shape *'回來。 –

+0

嗨Pileborg,感謝您的建議,我只是想知道他們之間的時差。我會檢查任何預定義的功能 – ranganath111

+0

嘗試一下並回報。 –

回答

7

測試類型然後執行static_cast的操作速度更快,但操作不相同,因爲它只允許向下轉換到最派生類型(任何中間級別都不會與typeid匹配)。我會使用dynamic_cast,因爲它更健壯(例如,如果有人擴展您的類型並傳遞指針,則不會中斷)。

如果dynamic_cast的性能在您的應用程序中出現問題,您應該重新考慮設計。雖然typeid + static_castdynamic_cast更快,但不必打開對象的運行時類型比其中任何一個更快。

1

我會想象任何像樣的編譯器都能夠將這兩個示例優化爲相同的代碼。但是,找出唯一的方法是衡量您的特定工具鏈的結果。

+0

實際上編譯器不能優化這種依賴於運行時信息的東西(也許他們可以用這個具體的例子,但是介紹編譯器不知道或者預測的任何東西,並且它會離開窗口)。 'typeid'比較兩個指針之間的單個比較,而'dynamic_cast'則遍歷繼承樹,所以理論上前者應該更快。但是,是的,你應該測量結果。 –

+0

@SethCarnegie我當然不是想暗示編譯器會優化RTTI,儘管我同意在一個非常簡單的情況下可能。相反,我認爲它可以推斷出'typeid'和'static_cast'這兩個用法只是一個簡單的'dynamic_cast'的用戶實現,並且在任何情況下都會輸出相同的代碼。 –

+0

那麼,'static_cast'和'typeid'這樣使用絕對不是'dynamic_cast'。正如我之前所說的,他們完全不同的東西:一個直接比較兩種類型,另一個比較多種類型。同樣,'dynamic_cast'在失敗時也有不同的行爲,所以編譯器會錯誤地將'static_cast'版本更改爲'dynamic_cast'。 –

3

這些代碼示例在邏輯上不相同。您忘記dynamic_cast將類繼承帶入該帳戶,並且比較typeid()僅比較繼承樹的部分部分。 typeid唯一給你的是「與該對象的實際類型相關的一些唯一標識符」。單獨使用typeid()時,您無法檢查是否可以對通用基址的指針進行強制轉換,您只能檢查其運行時類型是否與運行時類型完全相同。

說了這樣的話,我認爲static_cast + typeid在一般意義上應該更快一些,但在某些情況下會給出錯誤的答案。

+0

typeid在運行時僅爲您提供與實際對象類型相關的唯一標識符,不是嗎? 單獨的typeid()是不夠的?我認爲它執行了dynamic_cast的運行時檢查。我錯了請糾正我 – ranganath111

+1

是的,它只在運行時才起作用。在編譯時,它是未知的,你的比較都不能被優化。 – quetzalcoatl

+0

@ ranganath111:問題是,如果你有'A','B'和'C'的層次結構,'typeid',你只能測試對象是最派生類型'C',而不是它是一個'B'。如果你的代碼不關心實際類型是'C'還是'C'',而只是它在層次結構的'B'分支中,那可以用'dynamic_cast'而不是'typeid'來完成。另外請注意,開啓類型通常是一個糟糕的主意,使用'typeid'更是如此。如果將來有一段時間有人用'D'擴展層次結構,在任何條件下都不會匹配。 –