49

My understanding is that C++ reinterpret_cast and C pointer cast is a just a compile-time functionality and that it has no performance cost at all.

Is this true?

Sisir
  • 4,584
  • 4
  • 26
  • 37
fulmicoton
  • 15,502
  • 9
  • 54
  • 74

7 Answers7

63

It's a good assumption to start with. However, the optimizer may be restricted in what it can assume in the presence of a reinterpret_cast<> or C pointer cast. Then, even though the cast itself has no associated instructions, the resulting code is slower.

For instance, if you cast an int to a pointer, the optimizer likely will have no idea what that pointer could be pointing to. As a result, it probably has to assume that a write through that pointer can change any variable. That beats very common optimizations such as storing variables in registers.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 1
    I don't think "usually not" was the response you intended for the question "is this true?" – Rob Kennedy Aug 26 '10 at 16:11
  • @Rob Kennedy: Eh, yes. Reworded. – MSalters Aug 27 '10 at 07:56
  • 1
    thank you very much for this answer. Maybe in that case one may hint GCC with the register keyword (!?). – fulmicoton Aug 27 '10 at 10:08
  • 2
    Highly unlikely. On older implementations, the optimizer did little more than assign variables to registers. Using `register` would turn off that functionality. Nowadays, register assignment algorithms are much, much better. For instance, they can reuse a register for multiple variables, and assign a variable to a register for only part of its lifetime. As a result, the `register` keyword for a variable is effectively ignored. – MSalters Aug 30 '10 at 09:18
  • Is the same true for const_cast? – Mark Vincze Mar 13 '13 at 11:06
  • @Mark: That's far less likely. That cast doesn't produce new pointers or references, it merely affects what you can do with an existing one (writing, in particular). The optimizer will see the actual write and understand it. – MSalters Mar 13 '13 at 12:15
  • 1
    In light of your comment about the optimiser seeing the actual write, does that mean a reinterpret_cast between *only* pointer types will be optimised to have no runtime cost? – Ephemera Apr 01 '13 at 02:11
  • 1
    @PLPiper: That can harm another common optimization. If you write through a `float*` and then read through a `int*`, the optimizer usually can reorder the two statements. The write cannot affect the read, because the types differ. But if there's a preceding `reinterpret_cast` between a `int*` and `float*`, the optimizer is probably going to play it safe. – MSalters Apr 02 '13 at 06:24
  • Does a C-style cast have the same optimization issues in runtime? Do you reccomend a C-style cast over a `reinterpret_cast`? –  Aug 13 '14 at 07:47
  • 1
    @IngeHenriksen: A C cast is slightly worse, as it can do a little bit more (it can combine a `const_cast` and a `reinterpret_cast`). In practice I don't expect this to hinder the optimizer any further than the `reinterpret_cast` on its own. For readability reasons, prefer `reinterpret_cast`. C casts are hard to spot. – MSalters Aug 13 '14 at 07:50
6

That's right. No cost other than any gain/loss in performance for performing instructions at the new width, which I might add, is only a concern in rare cases. Casting between pointers on every platform I've ever heard of has zero cost, and no performance change whatsoever.

Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
5

C style casts in C++ will attempt a static_cast first and only perform a reinterpret_cast if a static cast cannot be performed. A static_cast may change the value of the pointer in the case of multiple inheritance (or when casting an interface to a concrete type), this offset calculation may involve an extra machine instruction. This will at most be 1 machine instruction so really very small.

doron
  • 27,972
  • 12
  • 65
  • 103
2

Yes, this is true. Casting type which has runtime cost is dynamic_cast.

Alex F
  • 42,307
  • 41
  • 144
  • 212
  • 4
    `static_cast` can have runtime cost as well; though it's usually just a single pointer adjustment, or code to covert one type to another (such as an `int` into a `float`) – Billy ONeal Aug 26 '10 at 13:04
  • Won't `static_cast` also call user-defined conversions? The runtime cost on those is unbounded. – Ben Voigt Aug 26 '10 at 13:13
  • Right, static_cast has runtime cost in the case of type (not pointer) conversion. My point is that dynamic_cast is the only cast type which has additional runtime cost, relatively to C casting. – Alex F Aug 26 '10 at 13:26
2

You're right, but think about it: reinterpret_cast means maybe a bad design or that you're doing something very low level.

dynamic-cast instead it will cost you something, because it has to look in a lookup table at runtime.

vulkanino
  • 9,074
  • 7
  • 44
  • 71
2

reinterpret_cast does not incur runtime cost.. however you have to be careful, as every use of reinterpret_cast is implementation defined. For example, it is possible reinterpreting a char array as an int array could cause the target architecture to throw an interrupt, because different types may have different alignment rules.

Get correct first, then worry about efficiency.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
0

I was looking at my assembler code before and after reinterpret casting signed char as unsigned char. The instructions grew by about 3 or four more instructions.

int main()
{
 signed char i = 0x80;
 (unsigned char&)i >>= 7;
 return i;
}

I was casting to unsigned char to make the compiler use SHL instruction, rather than SAR instruction, so that newly shifted shift in bits would be zer0s instead of var i signed bit value.

The compiler still and seems to always use SAR instruction. But the reinterpret casting made the compiler add more instructions. 3 to 4 more instructions!

I was concerned why my unicode function for converting UTF8 to UTF16 string was almost 3 times slower than Win32 MultiByteToWideChar(). Now I am worried that casting is one of the main factors.

Which is IRONIC, as we use reinterpret cast for speed.

user13947194
  • 337
  • 5
  • 7