[英]Why can't static_cast a double void pointer?
考慮以下代碼:
void **v_dptr(nullptr);
int **i_dptr = static_cast<int**>(v_dptr);
上面的示例產生以下編譯錯誤:
static_cast from 'void **' to 'int **' is not allowed
我知道將void
指針static_cast
為任何其他指針類型的正確方法是使用static_cast
。 但是,你不能static_cast
一個double void
指針指向另一個類型的另一個雙指針。
static_cast
一個雙void
指針? void
指針的正確方法? 當你有一個void*
並將它轉換為int*
,可能會或可能沒有一些數學/寬度調整來創建一個正確類型的實例, static_cast<>
將准備這樣做。 當你只有一個指向void*
的指針並想要一個指向int*
的指針時, static_cast<>
對指向的void*
對象沒有寫訪問權; 它是不是可以自由調整它以確保它是一個有效的int*
這樣static_cast<>
可以成功並返回一個真正可用於訪問有效int*
的指針。 雖然在某些體系結構上這可能無關緊要,但如果標准允許,那么代碼可能會在移植時中斷。 (請記住,期望static_cast<>
為使用static_cast<int*>(the_void_ptr)
初始化的int*
安排一些額外的內存是static_cast<int*>(the_void_ptr)
- 不僅會產生意外的開銷,而且還會需要在線程特定的內存中或動態分配並以某種方式釋放,並且實際最終比較指針值的所有代碼方式都會中斷。)
如果你想強迫這件事並向編譯器保證兩種類型的寬度相同並且不需要進行數學調整等等 - 那么你可以使用reinterpret_cast<>
並對其進行調整,明確表示你接受了風險未定義的行為。
void*
的特殊之處在於它可以指向任何東西。 它是“未指定類型的指針”。 因此,對於某些類型T
,轉換為void*
到T*
是“正常”操作, static_cast
可以支持該操作。 實際上,這樣的轉換說:“指針不知道它指向的是什么,但我知道它:它指向T
”
void**
這種方式並不特殊。 它只能指向一個事物,一個void*
。 將void**
轉換為int**
表示不同的東西:“指針聲稱它指向void*
,但我想將其視為指向int*
的指針。” 如果你想把一件事當作另一件事,你想要重新解釋原件 - 所以使用reinterpret_cast
。
我相信這是一個XY問題。 根據具體情況,可以在沒有reinterpret_cast
的情況下解決。 如果您知道void**
指針實際上指向指向int
的指針,則可以安全地執行此操作:
int* iptr = static_cast<int*>(*v_dptr);
除非你真的需要在你的代碼中使用int**
。 如果您需要,您可以:
int** i_dptr = &iptr;
但要注意它會指向一個局部變量iptr
,它會在超出范圍時被銷毀。
Q1的答案很好,Q2的答案在很大程度上取決於意圖。 如果void **v_dptr
旨在成為指向“泛型” void*
的指針,您知道它實際上是一個int*
並且您想要相應地進行轉換,以下可能是您想要的:
int *i_ptr = static_cast<int*>(*v_dptr);
int **i_dptr = &i_ptr;
static_cast
可以執行任何隱式轉換的反向操作。
有一個隱式轉換int*
→ void*
; 它不會丟失有關指向對象類型的信息。
沒有隱式轉換int**
→ void**
。 如果允許,它會重新解釋對象指針,即將int*
重新解釋為void*
。 在一些舊體系結構中, int*
不一定具有與void*
(或char*
,具有最小對齊要求的指針類型)一樣大的值表示。
重新解釋需要reinterpret_cast
。
恕我直言,這是用一個好主意reinterpret_cast
一般從轉換到/ void*
,因為意圖傳達給讀者。 但是,我記得Sutter和Alexandrescu推薦使用static_cast
,可能是因為C ++ 03缺乏正式的保證。 我還記得,在C ++ 11中修復了純正式的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.