[英]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.