Does reference to reference static_cast has the same run time cost as pointer to pointer static_cast?
E.g.
class B;
class A: public class B;
A obj;
A& ref = obj;
A* ptr = &obj;
// 1
static_cast<B&>(ref);
// 2
static_cast<B*>(ptr);
static_cast − This is used for the normal/ordinary type conversion. This is also the cast responsible for implicit type coersion and can also be called explicitly. You should use it in cases like converting float to int, char to int, etc. dynamic_cast −This cast is used for handling polymorphism.
The static_cast operator converts variable j to type float . This allows the compiler to generate a division with an answer of type float . All static_cast operators resolve at compile time and do not remove any const or volatile modifiers.
static_cast is always resolved using compile-time type info. (This may involve a runtime action). If it's not an appropriate cast you either get a compile error or undefined behaviour. In your snippet it is OK because b is a D ; however if b were new B() then the cast compiles but causes undefined behaviour if run.
If static_cast fails you will get a compile error and the program executable will never even be built. Your example has undefined behavior, not a failure or an error.
No, they do not always have the same cost. With optimizations turned on, they always have the same or very nearly the same cost.
If you are casting up or down an inheritance hierarchy in which either
Then a static_cast
of a pointer may incur the cost of a conditional move instruction whereas a static_cast
of a reference will not.
This is because a base class subobject might not have the same address as its complete object in these cases, so the static_cast
may involve applying an offset: adding or subtracting a constant to or from the address of the source type object to compute the address of the destination type object.
Pointers can be null, and a static_cast
of a null pointer must produce a null pointer, so if the pointer is null then the offset will not be applied. This means that the compiler must use a conditional move instruction to choose whether or not to apply the offset depending on whether or not the pointer is null.
References can not be null, so no conditional move is needed for a static_cast
of a reference. Also the this
pointer is immune, as the this
pointer can never be null.
Note that this also affects implicit derived-to-base conversions, not just explicit static_cast
.
The cost of a conditional move can usually be ignored. If the code is more readable or expressive using pointers then use pointers. Harming your code for the sake of avoiding a conditional move would almost always be very foolish.
Example:
struct A { int a; };
struct B { int b; };
struct C : A, B { int c; };
B* cast(C* ptr) { return ptr; }
B& cast(C& ref) { return ref; }
Compiler output: (latest GCC with -O2
)
cast(C*):
leaq 4(%rdi), %rax
testq %rdi, %rdi
movl $0, %edx
cmove %rdx, %rax
ret
cast(C&):
leaq 4(%rdi), %rax
ret
Note also that most compilers are smart enough to omit the conditional move if they can prove that the pointer can never be null. For example, if we insert int x = ptr->c;
before return ptr;
then the compiler will see the pointer indirection and will assume it can never null, because if it were null then the program has undefined behaviour anyway, so it wouldn't matter if an offset were applied to a null pointer. The code generated in that case would be the same as for a cast of a reference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With