Gibt es Fälle, in denen eine Klasse virtuelle Methoden und der Compiler erklärt benötigt keine vptr zu benutzen?

StackOverflow https://stackoverflow.com/questions/2336107

  •  22-09-2019
  •  | 
  •  

Frage

Ich habe mich gefragt, ob es eine mögliche Optimierung ist, wo der Compiler benötigte keine vptr zu einem instantiierten Objekt zuweisen, obwohl der Objekttyp eine Klasse mit virtuellen Methoden ist.

Zum Beispiel betrachten:

#include <iostream>
struct FooBase
{
  virtual void bar()=0;
};

struct FooDerived : public FooBase
{
  virtual void bar() { std::cout << "FooDerived::bar()\n"; }
};

int main()
{
   FooBase* pFoo = new FooDerived();
   pFoo->bar();

  return 0;
}

In diesem Beispiel sicherlich der Compiler weiß, was die Art der pFoo bei der Kompilierung, so dass es keine vptr für pFoo, Recht zur Nutzung benötigt? Gibt es weitere interessante Fälle, in denen der Compiler mit einem vptr vermeiden können?

War es hilfreich?

Lösung

Aufbauend auf Andrew Stein Antwort , weil ich denke, Sie auch wissen wollen, wenn die so genannten ‚Laufzeit-Overhead von virtuellen Funktionen‘ vermieden werden kann. (Der Overhead ist da, aber es ist winzige , und nur selten die Mühe wert.)

Es ist wirklich schwer, die Raum des VTable-Zeigers zu vermeiden, aber der Zeiger selbst kann ignoriert werden, in Ihrem Beispiel einschließlich. Da pFoo 's Initialisierung ist in diesem Umfang, der Compiler weiß, dass pFoo->bar bedeuten muss FooDerived :: bar , und braucht nicht die V-Tabelle zu überprüfen. Es gibt auch mehrere Caching-Techniken mehrere VTable-Lookups zu vermeiden, die von der einfachen bis zur komplexen.

Andere Tipps

Auch im Fall, dass Sie zeigen, bezweifle ich, dass jeder Compiler wird tun, was Sie vorschlagen.

Sie verwenden ein sehr einfaches Programm, alle in einer Datei.

Stellen Sie sich vor, dass Sie FooBase und FooDerived in foo.h und foo.cpp und Haupt in main.cpp hatte. Wenn foo.cpp kompiliert, wie ist der Compiler zu wissen, dass im gesamten Programm gibt es keine Notwendigkeit für eine vtbl ist. Es hat nicht gesehen main.cpp.

Die endgültige Festlegung kann nur zur Verknüpfungszeit gemacht werden, wenn es viel zu spät ist und kompliziert die Objektdatei zu ändern, werden alle Anrufe an sizeof (FooDerived) finden, usw.

Auch modernste, global optimierende Compiler klebt noch an das Prinzip der „unabhängiger Translation“. Nach diesem Prinzip wird jede Übersetzungseinheit ohne Kenntnisse über andere Übersetzungseinheiten unabhängig zusammengestellt, die im gesamten endgültigen Programm existieren könnten.

Wenn Sie eine Klasse mit externer Bindung erklären, diese Klasse kann auch in anderen Übersetzungseinheiten verwendet werden. Der Compiler hat keine Ahnung, wie Sie Ihre Klasse könnte in diesen anderen Übersetzungseinheiten verwendet werden. Also, es muss davon ausgehen, dass jede Instanz dieser Klasse könnte im Allgemeinen Notwendigkeit, ihre virtuellen Tabellenzeiger richtig zur Zeit der Konstruktion initialisiert.

In Ihrem Beispiel ein Smart-Compiler könnten herausfinden, dass der dynamische Typ von *pFoo Objekt FooDerived ist. Das würde es der Compiler den Code zu optimieren: einen direkten Aufruf zu FooDerived::bar Funktion als Reaktion auf pFoo->bar() Ausdruck zu erzeugen (ohne die virtuelle Tabelle zu verwenden). Aber dennoch würde der Compiler normalerweise immer noch richtig die virtuellen Tabellenzeiger in jedem FooDerived Objekt initialisieren.

Es ist möglich, dass ein Compiler des Indirektionsoperator Overhead der virtuellen Funktionsaufrufe zu schneiden, wenn es weiß, welche Methode der genauen Klasse wird aufgerufen werden. Dies ist das Ergebnis einer Form von Punkte-to Analyse, dass optimierende Compiler tun. Sie führen den Datenfluss von Zeigervariablen, und an jedem Ort ein Zeiger nur auf Objekte eines Typs zeigen kann, kann es Anrufe generieren für genau diese Art, Semantik virtuellen Call Implementierung statisch (das heißt bei der Kompilierung).

Wie viele andere gesagt haben, es sei denn, die Compiler Vollprogramm / link Zeitoptimierung tut (immer beliebter; GCC Gewinne es in 4.5), es muss noch eine Art Tabelle virtueller Funktionen erzeugen getrennte Sammlung zu unterstützen .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top