[英]C++: Safe way to cast an integer to a pointer
我需要將包含地址的整數類型轉換為實際的指針類型。 我可以按如下方式使用reinterpret_cast:
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);
使用第二種方法有什么優勢嗎?
不,這樣做沒有特定的優勢。 當您使用reinterpret_cast
,所有賭注都關閉了。 由您確定轉換是否有效。
實際上沒有嚴重的優勢。 如果void *指向不是多態對象的指針的對象,則您會立即遇到未定義的行為(通常是訪問沖突)。
對dynamic_cast
類型檢查由不同的C ++實現以不同的方式實現; 如果您想為特定的實現提供答案,則應提及您正在使用的實現。 通常,回答該問題的唯一方法是參考ISO標准C ++。
根據我對標准的閱讀,在void指針上調用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
指向最派生對象的指針。
安全的方法是保留所有活動的MyClass對象的記錄。 最好將此記錄保存在std::set<void*>
,這意味着您可以輕松地添加,刪除和測試元素。
將它們存儲為void*
的原因是,您不會像從整數創建未對齊的MyClass*
指針那樣冒着麻煩。
首先,將int
“重新解釋”為void *
是一個壞主意。 如果sizeof(int)
為4, sizeof(void *)
為8(64x系統),則格式錯誤。
此外, dynamic_cast
僅對多態類有效。
如果可以肯定地知道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。
選項1是您唯一的(半)便攜式/有效選項。
選項2:作為dynamic_cast無效的C ++(因為不允許void)。
在實現級別,它需要來自源類型的類型信息才能到達目標類型。 無法(或可能無法)從void *獲取運行時源類型信息,因此這也是無效的。
Dynamic_Cast用於提升和降低類型層次結構,而不是未知類型。
附帶說明一下,您可能應該使用void *而不是整數來存儲無類型的指針。 一個int的大小可能不足以存儲指針。
在C ++中處理指針的最安全方法是處理類型安全的指針。 這意味着:
原因是:您打算做的事是不安全的,可以避免,除非您與不安全的(舊版)代碼交互。 在這種情況下,請考慮MSalters的答案,但請注意,這仍然很麻煩。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.