2017-06-27 6 views
4

Hat die Referenz auf die Referenz static_cast die gleichen Laufzeitkosten wie der Zeiger auf den Zeiger static_cast?Kosten einer Referenz auf die Referenz static_cast und ein Zeiger auf den Zeiger static_cast

z.

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); 
+12

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. –

Antwort

3

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 
1

Es tut - und Sie können sicher davon ausgehen, dass die Kosten in beiden Fällen Null ist. Die einzige Spur von static_cast in der resultierenden Assembly (getestet mit MSVC++) ist eine zusätzliche Zeigerkopie, und selbst diese wird optimiert, wenn eine Optimierung aktiviert ist.

+0

Es hängt von der Objekthierarchie ab, dass im Fall von Mehrfachvererbung einige Laufzeitzeigerarithmetik benötigt wird – Motti

Verwandte Themen