我有一个指针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
答案 0 :(得分:9)
简短回答:你是对的。仅当pValues
类型为T[N]
时,强制转换才是安全的,并且您提到的两种情况(不同大小,动态分配的数组)很可能导致未定义的行为。< / p>
关于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));
成为可能。