5

If we use multiple inheritance, slicing will make the addresses to parent objects differ from the address to leaf objects:

struct X {int x};
struct Y {int y};
struct Z : X, Y {int z};

So if we have a Z object z, its address &z will not coincide with the address of its Y parent: static_cast<Y*>(&z) is four bytes higher than &z.

The good thing about static_cast is that it's, well, static, so doesn't take up runtime (compared to dynamic_cast, that is). However, if we have a Z* that points at 0, every cast to a parent should and does yield a null pointer as well. Why does this work and how is it implemented? Does that imply that every single static_cast introduces a branch instruction?

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
bitmask
  • 32,434
  • 14
  • 99
  • 159
  • This works because every object of the type `Z` is also an object of they type `Y`. A pointer can base class can implicitly point to objects of derived class. – Alok Save Jun 09 '12 at 14:30
  • 1
    @Als: I'm talking about the implementation of `static_cast`. Sure each `Z` contains a `Y` but their addresses differ. However, as you may note `static_cast(zPtr)` will `0` if `zPtr` is `0`. – bitmask Jun 09 '12 at 14:33
  • "it's, well, static, so doesn't take up runtime" -- huh? You do realise that a `static_cast` can also convert between integers of different sizes, don't you? That isn't (generally) a no-op at runtime either. –  Jun 09 '12 at 14:36
  • @hvd: Ah, yes. I was thinking "Compared to `dynamic_cast`" which requires rtti. – bitmask Jun 09 '12 at 14:37
  • Ah, that clears that up. But RTTI isn't always required for `dynamic_cast` either: at least in GCC, `dynamic_cast` works even with `fno-rtti`. –  Jun 09 '12 at 14:44

1 Answers1

8

Yes, both an implicit conversion from a pointer to a derived class to a pointer to a base class and a static_cast back again must preserve null pointer values. This means that a branch is usually required in the generated code for multiple inheritance cases where the base class address does not coincide with the derived class address.

It's theoretically possible for an implementation to reserve a range of addresses around a 'zero' address to represent null pointers and avoid the branch in this case but it would be at the expense of adding extra checking for comparisons of null pointers.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 1
    `but it would be at the expense of adding extra checking for comparisons of null pointers` which is a much more common scenario than static_casting to a parent. – orlp Jun 09 '12 at 15:01
  • 1
    @nightcracker: Absolutely. I can't imagine a practical implementation ever using this strategy; it's more of a thought exercise. – CB Bailey Jun 09 '12 at 15:04
  • @CharlesBailey: But note that quite a few implementations *do* actually reserve addresses near zero anyway. For example, on Windows the first four megabytes of address space is always "empty"--you can form such an address, but attempting to dereference it will get your program aborted. – Jerry Coffin Jul 13 '16 at 15:31