reinterpret_cast examples?

Started by
39 comments, last by Brother Bob 10 years, 11 months ago

Not sure about the virtual inheritance 4th case, I've never used virtual inheritance.

It is not used very often, but it solves a nasty problem of inheritance trees. See the article in Wikipedia for a description of the problem.

The standard libraries use it in several places, such as the I/O libraries.

Other than that, I have only seen it used a handful of times over decades of programming.

Advertisement

Yeah, I know what it is used for, I just don't like the sound of it. You can get the same effect with interfaces (abstract base classes) and multiple inheritance, it just requires more cut and paste or reimplementation, can you not? I don't think it's a good replacement for avoiding copy/paste code because of the gnarly problems... it is a hard problem though.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Concrete example for reinterpret cast:

You create an image buffer of x number of bytes. You calculate by bytes just in case there are issues with scan line alignment in this example. However, when you access each scanline, you know you are working with 32 bit data in your case, so you want to reference each scanline's memory using an unsigned int *.

Definitely want reinterpret_cast for that.

Example: unsigned int *pScan = reinterpret_cast<unsigned int *>(pBuffer8 + y * scanBytes);

Now you can address the pixels on that scan.

Now you can address the pixels on that scan.

With the caveat that the memory must be properly aligned.

The x86 family is almost unique that it will allow misaligned integer access. There is a nasty performance penalty for each read.

Most systems will simply crash on that line if you aren't lucky enough to have a correct alignment.

You can explicitly convert a pointer of a type A to a pointer of a type B if A is a base class of B. -> using static _cast

But isn't that the same thing a reinterpret_cast would do? What's the difference?

No, with multiple inheritance the reinterpret_cast will just cast the pointer, but static_cast will correctly adjust the pointer for the different base classes. Base and derived types are related, so you use static_cast which is used to cast between related types.

That's the difference between the two that I hinted at earlier; reinterpret_cast will just cast the type, but static_cast will also cast the value if necessary.

Now you can address the pixels on that scan.

With the caveat that the memory must be properly aligned.

The x86 family is almost unique that it will allow misaligned integer access. There is a nasty performance penalty for each read.

Most systems will simply crash on that line if you aren't lucky enough to have a correct alignment.

Fantastic point! That is very easy for me to forget sometimes. (Though the user may very well have considered this when allocating their image).

No, with multiple inheritance the reinterpret_cast will just cast the pointer, but static_cast will correctly adjust the pointer for the different base classes. Base and derived types are related, so you use static_cast which is used to cast between related types.

That's the difference between the two that I hinted at earlier; reinterpret_cast will just cast the type, but static_cast will also cast the value if necessary.

Ok,but isn't changing just the type enough? I mean it's a pointer,not an object.

No, changing the type is not enough.

struct base1 { };
struct base2 { };
struct derived : base1, base2 { };

int main(int, char**)
{
    base2 *b = new derived;
    base1 *br = reinterpret_cast<derived *>(b);
    base1 *bs = static_cast<derived *>(b);

    std::cout << b << std::endl;
    std::cout << br << std::endl;
    std::cout << bs << std::endl;
}

Here, b is a base2-pointer to a derived object, and br and bs are base1-pointers to the derived object typecast via the derived class using reinterpret_cast and static_cast, respectively.

The br pointer is an invalid cast because you have a base1 pointer incorrectly pointing to the base2 subclass of the derived object. The bs pointer is a valid pointer because you have a base1 pointer correctly pointing to the base1 subclass of the derived object.

Try the program, the two last pointers should be different. The cast requires changing the pointer's value as well as changing its type.

AFAIK (I am not a language lawyer) the only thing you can safely do after having performed a reinterpret_cast is to cast back again with another reinterpret_cast.

So you could not cast and then use the value for anything because it's implementation defined - in practice specific implementations make useful guarantees about things, but the C++ standard doesn't.

So a standards-compliant practical use of reinterpret_cast would be to pass a T* pointer through an API that only accepts, say, a void* or a char*. Then on the other side, you can cast it back to a T*.

I'd be interested to know if the standard does offer any additional guarantees?

In any case, use of reinterpret_cast makes me nervous.

This topic is closed to new replies.

Advertisement