[英]Why does Qt use reinterpret_cast rather than static_cast for void*?
[英]Is it valid to use void* rather than any pointer type if we always static_cast<> it?
假设我们有以下代码:
struct VeryComplexStruct {
// a very complex struct
void test() {}
};
void foo(VeryComplexStruct **ptr) {
// do something
}
int main() {
VeryComplexStruct *p = nullptr;
foo(&p);
p->test();
}
我想知道如果我们只使用void*
并像这样强制转换代码,C++ 标准的代码是否仍然有效:
struct VeryComplexStruct {
// a very complex struct
void test() {}
};
void foo(VeryComplexStruct **ptr) {
// do something
}
int main() {
void *p = nullptr;
foo(reinterpret_cast<VeryComplexStruct **>(&p));
(static_cast<VeryComplexStruct *>(p))->test();
}
如果我们在C++
中使用C
库,则可能会发生这种情况。 任何想法?
如果代码仍然有效
所呈现的代码(忽略p
指向 nullptr 并假设p
指向有效的VeryComplexStruct
对象)是有效的 - 您可以在指针值之间进行转换。 但是,如果您要访问指针:
struct VeryComplexStruct {
void test() {}
};
void foo(VeryComplexStruct **ptr) {
*ptr; // this here
}
int main() {
void *p = new VeryComplexStruct();
foo(reinterpret_cast<VeryComplexStruct **>(&p));
(static_cast<VeryComplexStruct *>(p))->test();
}
那将是无效的-您无法使用VeryComplexStruct **
句柄访问void **
指针,因此它有点违背了整个目的。 您必须使用void **
句柄访问void **
,例如reinterpret_cast<VeryComplexStruct*>(*reinterpret_cast<void**>(ptr))
。
任何想法?
Static 类型化语言是一项帮助您处理类型的功能 - 使用void *
您将把它全部扔掉 window。 坚持类型,只在需要时转换为void *
。
reinterpret_cast<VeryComplexStruct **>(&p)
不保证void*
和VeryComplexStruct*
的 alignment 要求兼容。 如果它们不是并且&p
没有为VeryComplexStruct*
适当地对齐,那么这个转换产生的值将是未指定的,并且基本上以任何方式使用它都会导致未定义的行为。
即使满足 alignment 要求,生成的指针也可能无法用于访问它指向的 object。 没有VeryComplexStruct*
object 与地址&p
处的void*
object指针可互转换。 因此,转换的结果仍将指向void*
object,而不是VeryComplexStruct*
object。
通常,通过另一种类型的左值(例如,取消引用的指针)访问一种类型的 object 是一种别名违规,导致未定义的行为,但有一些特定的例外情况,此处均不适用。
(甚至不能保证void*
和VeryComplexStruct*
具有相同的大小和表示形式,尽管实际上通常是这种情况。)
(static_cast<VeryComplexStruct *>(p))->test();
假设 function 没有修改p
,这是试图在 null 指针上调用非静态成员 function ,导致未定义的行为。
如果 function 确实以某种方式修改了p
,这基本上只有首先将参数转换回void**
才是合法的,那么这取决于 function 对p
做了什么。 如果为p
分配了一个指向VeryComplexStruct*
object 或某些 object 的指针,则该行有效,该指针与此类指针可相互转换。 否则,成员 function 调用将再次具有未定义的行为。
如果我们在 C++ 中使用 C 库,则可能会发生这种情况。 任何想法?
它在 C 中以相同的方式导致未定义的行为,尽管 object model 和使用的术语不同。 在这种情况下,问题将是void*
和VeryComplexStruct*
不是兼容的类型,因此通过指向VeryComplexStruct*
的指针访问void*
object 将再次违反别名。 因此,如果在 C 库中使用类似的东西,它已经依赖于未定义的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.