问题
According to cppreference.com, reinterpret_cast
:
Converts between types by reinterpreting the underlying bit pattern.
But wait, that\'s a lie cause it only works in these cases:
When a pointer or reference to object of type
T1
isreinterpret_cast
(or C-style cast) to a pointer or reference to object of a different typeT2
, the cast always succeeds, but the resulting pointer or reference may only be accessed if bothT1
andT2
are standard-layout types and one of the following is true:
T2
is the (possibly cv-qualified) dynamic type of the objectT2
andT1
are both (possibly multi-level, possibly cv-qualified at each level) pointers to the same typeT3
T2
is the (possibly cv-qualified) signed or unsigned variant of the dynamic type of the objectT2
is an aggregate type or a union type which holds one of the aforementioned types as an element or non-static member (including, recursively, elements of subaggregates and non-static data members of the contained unions): this makes it safe to cast from the first member of a struct and from an element of a union to the struct/union that contains it.T2
is a (possibly cv-qualified) base class of the dynamic type of the objectT2
ischar
orunsigned char
According to that list an illegal example would be:
auto foo = 13LL;
auto bar = reinterpret_cast<double&>(foo);
So the only acceptable way to make that cast is to copy the memory:
auto foo = 13LL;
double bar;
copy_n(reinterpret_cast<char*>(&foo), sizeof(foo), reinterpret_cast<char*>(&bar));
My question is, why doesn\'t reinterpret_cast
handle that for me? Or is there something else available so I don\'t have to jump through this hoop?
回答1:
why doesn't
reinterpret_cast
handle that for me?
One reason is that the size, alignment, and bit representations aren't specified, so such a conversion wouldn't be portable. However, that wouldn't really justify making the behaviour undefined, just implementation-defined.
By making it undefined, the compiler is allowed to assume that expressions of unrelated types don't access the same object, which can allow better optimisation. For example, in the following:
int & i = something();
float & f = something_else();
const int i1 = i;
f = 42;
const int i2 = i;
the compiler can assume that i1
and i2
both have the same value (i
being unchanged by the assignment to f
), and optimise them into a single constant. Breaking the assumption will then cause undefined behaviour.
Or is there something else available so I don't have to jump through this hoop?
Copying the bytes is the only well-defined way to reinterpret one object type as an unrelated type.
Aliasing with reinterpret_cast
or a union might work sometimes (assuming the size etc. match), but might trip you up if the optimiser gets too clever with undefined behaviour.
回答2:
Mainly the restrictions on reinterpret_cast
(not fully captured by the cppreference site) are because of
- alignment issues and
- trap representations.
For a hypothetical reinterpret_cast
to number value, different sizes can easily be handled by truncation or zero-extension, since one is into dangerous bit-level territory anyway, so that's not an issue.
By using memcpy
or copy_n
you work around the alignment issues, but you are still possible victim of trap representations. That means that use of the resulting value might blow up. On some platforms, for some values.
Note that the standard's guarantees about anything, can be and usually are extended by any particular compiler.
Often it can be a good idea to aim for just a little less portability than what you can have by relying solely on the standard.
For example, things get complicated fast when you can't assume that a byte is 8 bits. Making this assumption reduces portability. But still the set of supported platforms is large.
来源:https://stackoverflow.com/questions/28697626/why-doesnt-reinterpret-cast-force-copy-n-for-casts-between-same-sized-types