在C ++中使用static_cast转换指向数组引用的指针是否合法?

时间:2014-01-23 19:03:32

标签: c++ arrays casting type-safety static-cast

我有一个指针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来自以下任何构造,那么强制转换构造是否合法:

1

T theValues[N + M]; // M > 0
T * pValues = theValues;

2

T * pValues = new T[N + M]; // M >= 0

1 个答案:

答案 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));

成为可能。