2009-12-02 137 views
1

我需要將包含地址的整型轉換爲實際指針類型。我可以使用的reinterpret_cast如下:C++:將整型轉換爲指針的安全方法

MyClass *mc1 = reinterpret_cast<MyClass*>(the_integer); 

然而,這並不執行任何運行時檢查,看是否有問題的地址實際上持有MyClass的對象。我想知道在首先轉換爲void *(使用reinterpret_cast)並在結果中使用dynamic_cast方面是否有任何好處。像這樣:

void *p = reinterpret_cast<void*>(the_integer); 
MyClass *mc1 = dynamic_cast<MyClass*>(p); 
assert(mc1 != NULL); 

使用第二種方法有什麼好處嗎?

+4

第二種方法不是合法的C++,dynamic_cast表達式的類型可能不是void *。 – 2009-12-02 10:46:20

+2

假設整數值最初是一個對象的指針,那麼int可能不能保存指針。這就是爲什麼我們有無效*。如果您正在通過無類型邊界投射指針以進行傳輸,則應將它們轉換爲void *並返回到原始類型。 – 2009-12-02 10:50:54

+0

他沒有特別說'int',類型可能是intptr_t。 – 2009-12-02 10:53:41

回答

2

類型檢查dynamic_cast是由不同的C++實現以不同的方式實現;如果你想爲你的具體實現提供一個答案,你應該提及你正在使用的實現。一般回答問題的唯一方法是引用ISO標準C++。

通過我的標準的閱讀,對空指針調用dynamic_cast是非法的:

dynamic_cast<T>(v) 

「如果T是一個指針型,V應該是一個指針的右值來完成類類型」

(來自ISO C++標準的5.2.7.2)。 void不是完整的類類型,因此表達式是非法的。

有趣的是,類型被鑄造允許是空指針,即

void * foo = dynamic_cast<void *>(some_pointer); 

在這種情況下,dynamic_cast總是成功,將所得的值是一個指向最衍生對象指向v

+1

這是因爲在'void * foo = dynamic_cast (some_pointer);'之後,你可能會發現'foo!= some_pointer'(這意味着某個\ _pointer指向了一個基礎子對象)。 – 2009-12-02 10:49:36

2

不,這樣做沒有特別的優勢。在你使用reinterpret_cast的那一刻,所有投注都關閉。這取決於你確定演員是否有效。

2

其實沒有什麼重大的優勢。如果void *指向的東西不是指向多態對象的指針,則會立即遇到未定義的行爲(通常是訪問衝突)。

+2

除非你沒有。依靠未定義的行爲從來不是一個聰明的想法。 – 2009-12-02 10:45:16

1

安全的方法是記錄所有活MyClass對象。最好將此記錄保存在std::set<void*>之內,這意味着您可以輕鬆添加,刪除和測試元素。

將它們存儲爲void* s的原因是,您不會冒險像從您的整數中創建未對齊的指針MyClass*這樣的冒險。

0
  • 首先是 「重新詮釋」 intvoid *是一個壞主意。如果sizeof(int)是4並且sizeof(void *)是8(64x系統),則它是不合格的。

  • 此外dynamic_cast僅適用於多態類的情況。

0

如果你肯定知道the_integer指向一個已知的基類(即至少有一個虛擬成員),但實際上可能是一個優勢:知道對象是特定的派生類。但是你不得不reinterpret_cast到你的基類,然後再做dynamic_cast

BaseClass* obj = reinterpret_cast<BaseClass*>(the_integer); 
MyClass* myObj = dynamic_cast<BaseClass*>(obj); 

使用dynamic_cast一個void*是無用的,完全錯誤的。您不能使用dynamic_cast來檢查內存中某個任意位置是否有有效的對象。

在非指針類型變量中存儲地址時,還應該注意。有sizeof(void *)!= sizeof(int)的體系結構,例如LP64。

0

選項1是您唯一的(半)便攜式/有效選項。

選項2:與dynamic_cast無效C++(因爲void是不允許的)。

在實現級別,它需要來自源類型的類型信息才能到達目標類型。從void *獲取運行時源類型信息是沒有辦法的(或者可能沒有辦法),所以這也是無效的。

Dynamic_Cast用於對來自未知類型的類型層次結構進行升序和降級。

作爲一個附註,你應該使用void *而不是一個整數來存儲一個無類型的指針。 int有可能不足以存儲指針。

0

在C++中處理指針最安全的方法是處理它們的類型安全。這意味着:

  • 切勿將指針在別的不是一個指針
  • 避免空指針
  • 從來沒有過的指針其他進程
  • 考慮weak_ptr的,如果您計劃要使用的線程指針

原因是:你打算做的事情是不安全的,除非你與不安全(遺留)代碼交互,否則可以避免。在這種情況下,考慮MSalters的答案,但請注意,它仍然是一個麻煩。