Gibt es noch eine Verwendung für Inline? [Duplikat]

72

Ich glaube, inline war veraltet, weil ich hier gelesen habe:

  

Unabhängig davon, wie Sie eine Funktion als inline festlegen, ist dies eine Anforderung, die der Compiler ignorieren darf: Der Compiler kann einige, alle oder keine der Stellen, an denen Sie eine als% bezeichnete Funktion aufrufen, inline erweitern. co_de%.

Angew scheint jedoch etwas zu verstehen, was ich nicht verstehe. In dieser Frage gehen er und ich ziemlich oft hin und her, ob inline noch nützlich ist.

>

Diese Frage ist nicht eine Frage zu:

Wenn man bedenkt, dass der Compiler inline nach Belieben kann, ist inline dort nicht hilfreich: Wo kann inline verwendet werden, um zu erzwingen, nicht vorschlagen , eine Änderung im kompilierten Code?

    
Jonathan Mee 22.04.2015, 11:33
quelle

2 Antworten

59

Ich werde versuchen, mein "geheimes Verständnis" so gut wie möglich zu erklären.

Hier gibt es zwei völlig unterschiedliche Konzepte. Zum einen kann der Compiler einen Funktionsaufruf ersetzen, indem er den Funktionskörper direkt am Aufrufort wiederholt. Die andere Möglichkeit besteht darin, eine Funktion in mehr als einer Übersetzungseinheit zu definieren (= mehr als eine .cpp -Datei).

Der erste heißt Function Inlining. Die zweite ist der Zweck des Schlüsselworts inline . Historisch gesehen war das Schlüsselwort inline auch ein starker Vorschlag für den Compiler, die Funktion inline einzufügen. Da Compiler besser optimiert wurden, ist diese Funktionalität zurückgegangen, und die Verwendung von inline als Vorschlag zum Inline-Setzen einer Funktion ist in der Tat obsolet. Der Compiler wird es gerne ignorieren und etwas anderes komplett inline machen, wenn es eine bessere Optimierung findet.

Ich hoffe, wir haben uns mit der expliziten inline -inlining-Beziehung beschäftigt. Es gibt keinen im aktuellen Code.

Was ist der eigentliche Zweck des Schlüsselworts inline ? Ganz einfach: Eine mit inline gekennzeichnete Funktion kann in mehr als einer Übersetzungseinheit definiert werden, ohne die One Definition Rule (ODR) zu verletzen. Stellen Sie sich diese beiden Dateien vor:

Datei1.cpp

%Vor%

Datei2.cpp

%Vor%

Dieser Befehl:

%Vor%

Wird einen Linker-Fehler erzeugen und sich beschweren, dass das Symbol% ​​co_de% zweimal definiert ist.

Wenn Sie jedoch eine Funktion mit dem Schlüsselwort f markieren, teilt sie dem Compiler & amp; Linker: "Ihr Leute achtet darauf, dass mehrere identische Definitionen dieser Funktion nicht zu Fehlern führen!"

Also wird das Folgende funktionieren:

Datei1.cpp

%Vor%

Datei2.cpp

%Vor%

Das Kompilieren und Verknüpfen dieser zwei Dateien wird keine Linker-Fehler erzeugen.

Beachten Sie, dass die Definition von inline natürlich nicht wörtlich in den Dateien enthalten sein muss. Es kann stattdessen von einer f d-Header-Datei kommen:

f.hpp

%Vor%

Datei1.cpp

%Vor%

Datei2.cpp

%Vor%

Um eine Funktionsdefinition in eine Header-Datei schreiben zu können, müssen Sie sie als #include markieren, sonst führt dies zu mehreren Definitionsfehlern.

Das letzte Puzzleteil ist: Warum wird das Keyword tatsächlich als inline geschrieben, wenn es nichts mit Inlining zu tun hat? Der Grund ist einfach: Um eine Funktion zu inline zu bringen (dh um einen Aufruf durch Wiederholen ihres Körpers auf der Aufrufseite zu ersetzen), muss der Compiler den Funktionsblock an erster Stelle haben .

C ++ folgt einem separaten Kompilierungsmodell, bei dem der Compiler nicht auf andere Objektdateien zugreifen kann als die, die er gerade produziert. Um eine Funktion inline zu bilden, muss ihre Definition daher Teil der aktuellen Übersetzungseinheit sein. Wenn Sie es in mehr als einer Übersetzungseinheit einfügen möchten, muss die Definition in allen enthalten sein. Normalerweise würde dies zu einem Mehrfachdefinitionsfehler führen. Wenn Sie also Ihre Funktion in eine Kopfzeile einfügen und inline ihre Definition überall, damit sie überall inliniert werden kann, müssen Sie sie als #include markieren, um Mehrfachdefinitionsfehler zu vermeiden.

Beachten Sie, dass ein Compiler auch heute, wenn eine Funktion in der Lage ist, eine Funktion zu übernehmen, trotzdem Zugriff auf die Definition dieser Funktion haben muss. Während also das Schlüsselwort inline nicht als Hinweis "Bitte inline dieses" benötigt wird, müssen Sie es möglicherweise noch verwenden, um den Compiler für das Inlining aktivieren zu aktivieren, wenn er dies wünscht. Ohne es wäre es vielleicht nicht möglich, die Definition in die Übersetzungseinheit zu bringen, und ohne die Definition kann der Compiler die Funktion einfach nicht inline einbinden.

Der Compiler kann nicht. Der Linker kann. Zu den modernen Optimierungstechniken gehört die Erzeugung von Link-Time-Codes (auch als "Whole Program Optimization" bezeichnet), bei der der Optimierer vor dem eigentlichen Linken als Teil des Verknüpfungsprozesses über alle Objektdateien läuft. In diesem Schritt sind natürlich alle Funktionsdefinitionen verfügbar und Inlining ist perfekt möglich, ohne dass ein einziges inline -Schlüsselwort irgendwo im Programm verwendet wird. Diese Optimierung ist jedoch in der Regel kostenintensiv, insbesondere bei großen Projekten. In diesem Sinne ist es möglicherweise nicht die beste Option, sich ausschließlich auf LTCG für das Inlining zu verlassen.

Der Vollständigkeit halber: Ich habe im ersten Teil etwas betrogen. Die ODR-Eigenschaft ist eigentlich keine Eigenschaft des Schlüsselworts inline , sondern von Inline-Funktionen (was ein Begriff der Sprache ist). Die Regeln für Inline-Funktionen sind:

  • Kann in mehreren Übersetzungseinheiten definiert werden, ohne Linker-Fehler zu verursachen
  • Muss in jeder Übersetzungseinheit definiert sein, in der es verwendet wird
  • Alle seine Definitionen müssen Token-für-Token und Entity-für-Entity-identisch sein

Das Schlüsselwort inline macht aus einer Funktion eine Inline-Funktion.Eine andere Möglichkeit, eine Funktion als Inline zu markieren, besteht darin, sie direkt in einer Klassendefinition zu definieren (nicht nur zu deklarieren). Eine solche Funktion ist automatisch inline, auch ohne das inline Schlüsselwort.

    
Angew 22.04.2015, 11:57
quelle
42

inline ist jetzt meistens nur ein externer Verknüpfungsspezifizierer, aus den von Ihnen angegebenen Gründen.

Also ja, es hat eine Verwendung, aber es ist ein anderes als tatsächlich inlining Funktionen. Es ermöglicht Ihnen, dieselbe Methode mehrmals zwischen den Kompilierungseinheiten zu definieren und sie richtig zu verknüpfen, anstatt mehrere Definitionsfehler zu erhalten.

%Vor%

Das Erzwingen von Funktionsinlining ist Sache des Compilers. Einige könnten Unterstützung über spezifische attribute s oder pragma s oder ( __forceinline ) oder whatnot.

haben

Einfach gesagt, erlaubt es Ihnen, Funktionen in Kopfzeilen zu definieren, ohne die ODR zu unterbrechen ...

    
Luchian Grigore 22.04.2015 11:36
quelle