Nein, sie haben nicht immer die gleichen Kosten. Mit optimierten Optimierungen haben sie immer die gleichen oder fast gleichen Kosten.
Wenn Sie nach oben oder unten einer Vererbungshierarchie werfen, in denen entweder
- Mehrfachvererbung beteiligt ist, oder
- eine polymorphe Klasse erbt von einer nicht-polymorphen Klasse,
Dann Ein static_cast
eines Zeigers kann die Kosten eines conditional move Befehls verursachen, während ein static_cast
einer Referenz nicht wird.
Dies ist, weil eine Basisklasse Subobjekt nicht die gleiche Adresse als sein komplettes Objekt in diesen Fällen haben könnte, so dass eine der static_cast
beinhalten kann Anwendung offset: Zugabe oder eine Konstante zu oder von der Adresse des Quellentyp Objekt Subtrahieren Berechnen Sie die Adresse des Zieltypobjekts.
Zeiger können null sein, und ein static_cast
eines Null-Zeigers muss einen Nullzeiger erzeugen, wenn der Zeiger also null ist, wird der Offset nicht angewendet. Dies bedeutet, dass der Compiler einen bedingten Verschiebungsbefehl verwenden muss, um auszuwählen, ob der Offset angewendet werden soll oder nicht, abhängig davon, ob der Zeiger Null ist oder nicht.
Referenzen können nicht Null sein, daher ist keine bedingte Verschiebung für eine static_cast
einer Referenz erforderlich. Auch der Zeiger this
ist immun, da der Zeiger this
niemals null sein kann.
Beachten Sie, dass dies auch implizite Konvertierungen von abgeleiteten in Basiswerte betrifft, nicht nur explizite static_cast
.
Die Kosten einer bedingten Bewegung können normalerweise ignoriert werden. Wenn der Code mit Zeigern lesbarer oder aussagekräftiger ist, dann verwenden Sie Zeiger. Deinen Code zu beschädigen, um einen bedingten Umzug zu vermeiden, wäre fast immer sehr dumm.
Beispiel:
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-Ausgang: (neueste GCC mit -O2
)
cast(C*):
leaq 4(%rdi), %rax
testq %rdi, %rdi
movl $0, %edx
cmove %rdx, %rax
ret
cast(C&):
leaq 4(%rdi), %rax
ret
Wenn Sie sich Gedanken darüber zu starten, dann haben Sie mit Ihrem zu weit ein paar Schritte gegangen * vorzeitige Optimierungen *. Konzentriere dich darauf, guten, lesbaren, gut dokumentierten, wartbaren und funktionierenden Code zu erstellen.Dann testen Sie Ihre Anwendung, und wenn sie nicht den möglichen Leistungsanforderungen entspricht (und denken Sie daran, dass "gut genug" oft gut genug ist), dann messen, profilieren und benchmarken Sie, um die Hot-Spots und Engpässe zu finden konzentrieren Sie Ihre Optimierungsbemühungen nur auf diese und denken Sie daran, alles zu dokumentieren. –