Fügt 'finaler' Spezifizierer Overhead hinzu?

8

Fügt die Verwendung von specifier final in class oder in function Speicher- oder CPU-Overhead hinzu oder wird sie nur zur Kompilierzeit verwendet?

Und wie erkennt std::is_final , was endgültig ist?

    
Laurynas Lazauskas 12.08.2015, 14:12
quelle

2 Antworten

21

Es kann tatsächlich den Overhead reduzieren. Und in seltenen Fällen, erhöhen Sie es.

Wenn Sie einen Zeiger auf eine final class A haben, können alle virtuellen Methodenaufrufe de-virtualisiert und direkt aufgerufen werden. Ebenso kann ein Aufruf einer virtuellen Methode final de-virtualisiert werden. Darüber hinaus ist der Vererbungsbaum einer final -Klasse fest, selbst wenn er virtual Elternklassen enthält, so dass Sie einige Eltern-Zugriffe de-virtualisieren können.

Jede dieser De-Virtualisierungen reduziert oder eliminiert die Anforderung, dass eine Laufzeitstruktur (die vtable) abgefragt werden muss.

Es kann einen leichten Nachteil geben. Einige Codiertechniken beruhen auf dem vtable-Zugriff, um den direkten Zugriff auf ein Symbol zu vermeiden, und exportieren das Symbol dann nicht. Der Zugriff auf eine vtable kann über Konvention erfolgen (ohne Symbole aus einer Bibliothek, nur die Header-Datei für die fraglichen Klassen), während der Zugriff auf eine Methode direkt eine Verknüpfung mit diesem Symbol erfordert.

Dies bricht eine Form der dynamischen C ++ - Bibliotheksverknüpfung (wobei Sie vermeiden, mehr als ein dll-Ladesymbol und / oder C-Verknüpfungsfunktionen, die Zeiger zurückgeben, zu verknüpfen, und Klassen werden über ihre VTables exportiert).

Es ist auch möglich, dass wenn Sie eine Verknüpfung mit einem Symbol in einer dynamischen Bibliothek herstellen, das Laden des dynamischen Bibliothekssymbols teurer sein könnte als das Suchen mit vtable. Ich habe das nicht erlebt oder profiliert, aber ich habe es gesehen. Die Vorteile sollten diese Kosten im Allgemeinen überwiegen. Alle diese Kosten stellen eine Qualität der Implementierung dar, da die Kosten nicht auftreten müssen, weil die Methode final ist.

Schließlich verhindert final den Trick der leeren Basisoptimierung bei Klassen, wo jemand weiß, dass Ihre Klasse keinen Status hat, und erbt von ihr, um den Aufwand beim "Speichern" einer Instanz Ihrer Klasse von 1 Byte auf 0 Byte zu reduzieren. Wenn Ihre Klasse leer ist und keine virtuellen Methoden / Vererbung enthält, verwenden Sie nicht final , um zu verhindern, dass diese Klasse blockiert wird. Es gibt keine Entsprechung für final -Funktionen.

Abgesehen von dem Problem der EBO-Optimierung (das nur bei leeren Typen auftritt), kommt jeder Overhead von final daher, wie anderer Code damit interagiert, und wird selten sein. Weitaus häufiger wird es anderen Code schneller machen, da die direkte Interaktion mit einer Methode einen direkteren Aufruf der Methode ermöglicht und zu Anklopfoptimierungen führen kann (weil der Aufruf vom Compiler besser verstanden werden kann). p>

Das Markieren von irgendetwas außer einem leeren Typ als final , wenn es endgültig ist, ist zur Laufzeit harmlos. Dies kann bei Klassen mit virtuellen Funktionen und Vererbung zur Laufzeit vorteilhaft sein.

std::is_final und ähnliche Merkmale werden fast alle über die eingebaute Magie des Compilers implementiert. Eine gute Anzahl der Eigenschaften in std benötigt eine solche Magie. Siehe Wie erkennt man, ob eine Klasse in C ++ 11 final ist? (Danke an @Csq für das Finden)

    
Yakk 12.08.2015, 14:46
quelle
4
  1. Nein, es wird nur zur Kompilierzeit verwendet

  2. Magie ( siehe hier für weitere Informationen - danke Csq für den Link)

M.M 12.08.2015 14:14
quelle

Tags und Links