我有一个指针T * pValues
,我想将其视为T (&values)[N]
在这个SO答复https://stackoverflow.com/a/2634994/239916中,建议的实现方法是
T (&values)[N] = *static_cast<T(*)[N]>(static_cast<void*>(pValues));
我对此感到担忧。在他的示例中,pValues
通过以下方式初始化
T theValues[N];
T * pValues = theValues;
我的问题是,如果pValues
来自以下任一构造,则强制转换构造是否合法:
T theValues[N + M]; // M > 0
T * pValues = theValues;
T * pValues = new T[N + M]; // M >= 0
简短的回答:你是对的。仅当pValues
类型为,T[N]
并且您提到的两种情况(大小不同,动态分配的数组)都很可能导致不确定的行为时,转换才是安全的。
有趣的static_cast
是,在编译时进行了一些额外的检查,因此,如果您似乎做错了什么,编译器会抱怨它(相比之下,丑陋的C样式强制转换几乎可以执行任何操作),例如:
struct A { int i; };
struct C { double d; };
int main() {
A a;
// C* c = (C*) &a; // possible to compile, but leads to undefined behavior
C* c = static_cast<C*>(&a);
}
会给你: invalid static_cast from type ‘A*’ to type ‘C*’
在这种情况下,您将void*
其强制转换为,从可以在编译时进行检查的角度来看,它几乎对任何事物都是合法的,反之亦然:void*
也可以强制转换为几乎所有事物,这使得使用static_cast
完全没有用处因为这些检查变得毫无用处。
对于前面的示例:
C* c = static_cast<C*>(static_cast<void*>(&a));
没有比:
C* c = (C*) &a;
并很可能导致该指针的错误使用和未定义的行为。
换一种说法:
A arr[N];
A (&ref)[N] = *static_cast<A(*)[N]>(&arr);
很安全,也很好。但是一旦您开始滥用行为static_cast<void*>
,就无法保证会发生什么,因为即使是这样的事情:
C *pC = new C;
A (&ref2)[N] = *static_cast<A(*)[N]>(static_cast<void*>(&pC));
成为可能。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句