问题
Is it legal as per the C++ standard to convert a pointer or reference to a fixed array (e.g. T(*)[N]
or T(&)[N]
) to a pointer or reference to a smaller fixed array of the same type and CV qualification (e.g. T(*)[M]
or T(&)[M]
)?
Basically, would this always be well-formed for all instantiations of T
(regardless of layout-type):
void consume(T(&array)[2]);
void receive(T(&array)[6])
{
consume(reinterpret_cast<T(&)[2]>(array));
}
I don't see any references to this being a valid conversion in:
- expr.reinterpret.cast,
- expr.static.cast,
- conv.array, or even
- basic.types
However, it appears that all major compilers accept this and generate proper code even when optimized when using T = std::string
(compiler explorer)(not that this proves much, if it is undefined behavior).
It's my understanding that this should be illegal as per the type-system, since an object of T[2]
was never truly created, which means a reference of T(&)[2]
would be invalid.
I'm tagging this question c++11 because this is the version I am most interested in the answer for, but I would be curious to know whether this answer is different in newer versions a well.
回答1:
There’s not much to say here except no, in any language version: the types are simply unrelated. C++20 does allow conversion from T (*)[N]
to T (*)[]
(and similarly for references), but that doesn’t mean you can treat two different N
s equivalently. The closest you’re going to get to a “reference” for this rule is [conv.array]/1 (“The result is a pointer to the first element of the array.”, which T[2]
does not exist in your example) and a note in [defns.undefined] (“Undefined behavior may be expected when this document omits any explicit definition of behavior”).
Part of the reason that compilers don’t “catch” you is that such reinterpret_cast
s are valid to return to the real type of an object after another reinterpret_cast
used to “sneak” it through an interface that expects a pointer or reference to a different type (but doesn’t use it as that type!). That means that the code as given is legitimate, but the obvious sort of definition for consume
and caller for receive
would together cause undefined behavior. (The other part is that optimizers often leave code alone that’s always undefined unless it can eliminate a branch.)
来源:https://stackoverflow.com/questions/64539646/is-it-legal-to-convert-a-pointer-reference-to-a-fixed-array-size-to-a-smaller-si