Your Browser is not longer supported

Please use Google Chrome, Mozilla Firefox or Microsoft Edge to view the page correctly
Loading...

{{viewport.spaceProperty.prod}}

Automatische Instanziierung

&pagelevel(4)&pagelevel

Der Compiler unterstützt als Voreinstellung in den Sprachmodi C++ V3, C++ 2017 und C++ 2020 die automatische Instanziierung (Option -T auto). Dadurch können Sie Quellcode übersetzen und die erzeugten Objekte binden, ohne sich um die notwendigen Instanziierungen kümmern zu müssen.

Im Folgenden beziehen sich die Erläuterungen zur automatischen Instanziierung auf Template-Einheiten, für die es keine explizite Instanziierungsanforderung (template declaration) und kein instantiate-Pragma gibt.

Voraussetzungen

Der Compiler erwartet dabei für jede Instanziierung eine Quelldatei, die sowohl eine Referenz auf die benötigte Instanz enthält als auch die Definition der Template-Einheit und aller für die Instanziierung der Template-Einheit benötigten Typen. Um die letzten beiden Anforderungen zu erfüllen, haben Sie folgende Möglichkeiten:

  • Jede .h-Datei, in der eine Template-Einheit deklariert ist, enthält entweder auch die Definition der Template-Einheit oder inkludiert eine Datei, die diese Definition enthält.

  • Implizites Inkludieren
    Wenn der Compiler eine Template-Deklaration in einer .h-Datei findet und auf eine Instanziierungsanforderung stößt, sucht er nach einer Quelldatei mit dem Basisnamen der .h-Datei und einem Suffix, das den C++-Quelldatei-Konventionen genügt (siehe Regeln für Eingabedateinamen, "Aufruf-Syntax und allgemeine Regeln"). Diese Datei wird beim Instanziieren ohne Meldung am Ende der jeweiligen Übersetzungseinheit inkludiert. Weitere Einzelheiten siehe Abschnitt "Implizites Inkludieren“.

  • Der Programmierer stellt sicher, dass die Dateien, die Template-Einheiten definieren, auch die Definitionen der benötigten Typen enthalten, und fügt in diese Dateien C++-Code oder Instanziierungs-Pragmas ein, mit denen die Instanziierung der dortigen Template-Einheiten angefordert wird.

Erste Instanziierung ohne Definitionsliste

Alternativ zu dem folgenden Verfahren kann auch das Definitionslisten-Verfahren angewandt werden (siehe "Erste Instanziierung mithilfe der Definitionsliste (temporäres Repository)").

Bei der automatischen Instanziierung werden intern folgende Schritte durchgeführt:

  1. Instanziierungs-Informationsdateien erzeugen
    Wenn eine oder mehrere Quelldateien zum ersten Mal übersetzt werden, werden noch keine Template-Einheiten instanziiert. Für jede Quelldatei, die ein Template benutzt, wird, falls noch nicht vorhanden, eine Instanziierungs-Informationsdatei erzeugt. Eine Instanziierungs-Informationsdatei hat das Suffix .o.ii. Bei der Übersetzung von abc.C würde z.B. die Datei abc.o.ii erzeugt werden. Die Instanziierungs-Informationsdatei darf vom Benutzer nicht verändert werden.

  2. Objektdateien erzeugen
    Die erzeugten Objekte enthalten Informationen darüber, welche Instanzen bei der Übersetzung einer Quelldatei erzeugt werden könnten und ggf. benötigt werden.

  3. Template-Instanziierungen zuweisen
    Wenn die Objektdateien gebunden werden, wird vor dem eigentlichen Binden der Prälinker aufgerufen. Dieser durchsucht die Objektdateien nach Referenzen und Definitionen von Template-Einheiten und nach zusätzlichen Informationen über erzeugbare Instanzen. Wenn er keine Definition einer benötigten Template-Einheit findet, sucht er nach einer Objektdatei, in der angegeben ist, dass sie die Template-Einheit instanziieren könnte. Wenn er eine solche Datei findet, weist er die Instanziierung dieser Datei zu.

  4. Instanziierungs-Informationsdatei aktualisieren
    Für alle Instanziierungen, die einer Datei zugewiesen wurden, werden in der zugehörigen Instanziierungs-Informationsdatei die Namen der entsprechenden Instanzen geschrieben.

  5. Nachübersetzen
    Der Compiler wird intern erneut aufgerufen, um alle Dateien nachzuübersetzen, deren Instanziierungs-Informationsdatei verändert wurde.

  6. Neue Objektdatei erzeugen
    Wenn der Compiler eine Datei übersetzt, liest er die Instanziierungs-Informationsdatei für diese Übersetzungseinheit und erzeugt eine neue Objektdatei mit den benötigten Instanzen.

  7. Wiederholung
    Die Schritte 3 bis 6 werden solange wiederholt, bis alle benötigten und generierbaren Instanzen erzeugt sind.

  8. Binden
    Die Objektdateien werden gebunden.

Erste Instanziierung mithilfe der Definitionsliste (temporäres Repository)

Da das obige Verfahren (siehe "Erste Instanziierung ohne Definitionsliste") einige Dateien mehr als einmal nachübersetzt (rekompiliert), wurde eine Option hinzugefügt, die den gesamten Prozess beschleunigen soll.

Dabei werden die Dateien in der Regel nur einmal nachübersetzt. Durch das Verfahren wird der Hauptanteil der Instanziierungen den ersten nachzuübersetzenden Dateien zugeordnet. Dies hat in einigen Fällen Nachteile, da dadurch ihre Objektgröße ansteigt (als Ausgleich werden andere Objekte kleiner).

Das Vergrößern einzelner Module kann in Benutzeranwendungen von Nachteil sein, wenn z.B. genau diese Module häufig geladen werden müssen. Der Benutzer muss deshalb selbst entscheiden, ob die gleichmäßigere Verteilung der Instanzen (default-Verfahren) oder dieses Verfahren (besseres Zeitverhalten während des Prälinkens) gewollt ist.

Dieses Schema kann durch Angabe der Option -T definition_list aktiviert werden. Die obigen Schritte 3-5 werden modifiziert. Damit sieht der Algorithmus folgendermaßen aus:

  1. Instanziierungs-Informationsdateien erzeugen
    Wenn eine oder mehrere Quelldateien zum ersten Mal übersetzt werden, werden noch keine Template-Einheiten instanziiert. Für jede Quelldatei, die ein Template benutzt, wird, falls noch nicht vorhanden, eine Instanziierungs-Informationsdatei erzeugt. Eine Instanziierungs-Informationsdatei hat das Suffix .o.ii. Bei der Übersetzung von abc.C würde z.B. die Datei abc.o.ii erzeugt werden. Die Instanziierungs-Informationsdatei darf vom Benutzer nicht verändert werden.

  2. Objektdateien erzeugen
    Die erzeugten Objekte enthalten Informationen darüber, welche Instanzen bei der Übersetzung einer Quelldatei erzeugt werden könnten und ggf. benötigt werden.

  3. Template-Instanzen einer Sourcedatei zuordnen
    Falls es Referenzen für Template-Einheiten gibt, für die es keine Definitionen im Satz der Objektdateien gibt, so wird eine Datei ausgewählt, die eine der Template-Einheiten instanziieren könnte. Alle Template-Einheiten, die in dieser Datei instanziiert werden können, werden dieser zugeordnet.

  4. Instanziierungs-Informationsdatei aktualisieren
    Der Satz an Instanziierungen, der dieser Datei zugeordnet ist, wird in der assoziierten Instanziierungs-Datei aufgezeichnet.

  5. Speichern der Definitionsliste
    Intern wird eine Definitionsliste im Speicher gehalten. Sie enthält eine Liste aller Template-bezogenen Definitionen, die in allen Objektdateien gefunden wurden. Diese Liste kann während des Nachübersetzens gelesen und verändert werden.

    Hinweis
    Diese Liste wird nicht in einer Datei abgelegt.

  6. Nachübersetzen
    Der Compiler wird intern erneut aufgerufen, um die korrespondierende Quelldatei nachzuübersetzen.

  7. Neue Objektdatei erzeugen
    Wenn der Compiler eine Datei nachübersetzt, liest er die Instanziierungs-Informationsdatei für diese Übersetzungseinheit und erzeugt eine neue Objektdatei mit den benötigten Instanzen.
    Wenn der Compiler während der Übersetzung die Gelegenheit erhält, weitere referenzierte Template-Einheiten zu instanziieren, die nicht in der Definitionsliste erwähnt sind oder in den aufgelösten Bibliotheken nicht gefunden wurden, führt er auch diese Instanziierungen durch (z. B. bei Templates, die in Templates enthalten sind). Er führt dem Prälinker eine Liste der Instanziierungen zu, die er auf seinem Weg erhalten hat, so dass der Prälinker sie der Datei zuordnen kann.
    Dieser Prozess erlaubt schnellere Instanziierung. Zudem reduziert sich die Notwendigkeit, eine bestehende Datei während des Prälink-Prozesses mehr als einmal nachzuübersetzen.

  8. Wiederholung
    Die Schritte 3 - 7 werden solange wiederholt, bis alle benötigten und generierbaren Instanzen erzeugt sind.

  9. Binden
    Die Objektdateien werden gebunden.

Weiterentwicklung

Wenn ein Programm korrekt gebunden wurde, enthalten die zugehörigen Instanziierungs-Informationsdateien alle Namen der definierten und benötigten Instanzen. Von da an zieht der Compiler, wenn eine Quelldatei erneut übersetzt wird, die Instanziierungs-Informationsdatei zu Rate und instanziiert wie bei einem normalen Übersetzungslauf. Das heißt, außer in Fällen, in denen Veränderungen an den Instanzen gemacht werden, sind alle für den Prälinker nötigen Instanziierungen in den Objektdateien gespeichert und keine Instanziierungsanpassungen mehr nötig. Das ist auch der Fall, wenn das Programm vollständig neu übersetzt wird.

Eine irgendwo im Programm bereitgestellte Spezialisierung einer Template-Einheit betrachtet der Prälinker als Definition. Da diese Definition beliebig auftretende Referenzen auf diese Template-Einheit befriedigt, sieht der Prälinker keine Notwendigkeit, eine Instanz für die Template-Einheit anzufordern. Wenn eine Spezialisierung zu einem Programm hinzugefügt wird, das vorher schon einmal übersetzt wurde, löscht der Prälinker die Instanziierungszuweisung aus der entprechenden Instanziierungs-Informationsdatei.

Bis auf folgende Ausnahme darf die Instanziierungs-Informationsdatei vom Benutzer nicht verändert, z.B. umbenannt oder gelöscht werden: Im selben Compilerlauf wird zuerst eine Quelldatei übersetzt, in der eine Definition verändert wurde und anschließend eine Quelldatei, in die eine Spezialisierung eingefügt wurde. Wenn nun die Übersetzung der ersten Datei (mit der geänderten Definition) mit Fehler abgebrochen wird, muss die zugehörige Instanziierungs-Informationsdatei von Hand gelöscht werden, damit sie vom Prälinker neu generiert werden kann.

Automatische Instanziierung, Bibliotheken und vorgebundene Objektdateien

Wenn mit dem CC-Kommando eine ausführbare Datei im automatischen Instanziierungsmodus erzeugt wird, führt der Prälinker die automatische Instanziierung nur in einzelnen Objektdateien (.o-Dateien) durch, nicht jedoch in Objekten, die Bestandteil einer Bibliothek (.a-Bibliothek) oder einer mit der Option -r vorgebundenen Objektdatei sind.

Bibliotheken oder vorgebundene Objektdateien, die Instanzen von Template-Einheiten benötigen, müssen beim Erzeugen der ausführbaren Datei

  • entweder diese Instanzen bereits enthalten; dies kann durch explizite Instanziierung und/oder das Vorinstanziieren der Objekte über die Option -y erreicht werden (siehe auch Option -y, "Optionen zur Auswahl von Übersetzungsphasen")

  • oder entsprechende Include-Dateien mit can_instantiate-Pragmas bereitstellen.

Weitere Einzelheiten siehe Abschnitt "Bibliotheken und Templates“.

Die Option -T add_prelink_files stellt eine weitere Möglichkeit dar, die automatische Instanziierung im Zusammenhang mit Bibliotheken zu steuern (siehe "Template-Optionen").

Steuerung der Instanziierungszuweisungen

Die Zuweisung von Instanziierungen an lokale Objektdateien kann durch die Option -K assign_local_only an- und durch die Option -K no_assign_local_only abgeschaltet werden (siehe "Template-Optionen").