Bearbeiten : Ich habe den ursprünglichen Titel wiederhergestellt, aber eigentlich hätte ich Folgendes gefragt: "Wie behandeln C ++ - Linker Klassenmethoden, die in mehreren Objektdateien definiert wurden"
Angenommen, ich habe eine C ++ - Klasse in einer Kopfzeile definiert:
%Vor%Wenn ich einen C ++ - Code kompiliere, der 'Obnoxiously_Large_Method' an mehreren Stellen verwendet, wird die resultierende Objektdatei immer den Code für 'Obnoxiously_Large_Method' inline oder wird er für die Größe optimiert (zB wenn g ++ -Os verwendet wird) einzelne Instanz von 'Obnoxiously_Large_Method' und verwenden Sie es wie eine normale Funktion ?, Wenn ja, wie Linker die Kollisionen zwischen anderen Objektdateien auflösen, die die gleiche Funktion instanziiert haben ?. Gibt es einen obskuren C ++ - Namespace Juju, der verhindert, dass die separaten Objektinstanzen der Methode miteinander kollidieren?
7.1.2 Funktionsbezeichner
Eine Funktionsdeklaration (8.3.5, 9.3, 11.4) mit einem Inline-Spezifizierer erklärt eine Inline-Funktion. Der Inline-Spezifizierer zeigt dem Implementierung, die Inline-Substitution des Funktionskörpers an der Point of Call ist dem üblichen Funktionsaufrufmechanismus vorzuziehen. Für diese Inline-Substitution ist keine Implementierung erforderlich zum Zeitpunkt des Anrufs; selbst wenn diese Inline-Substitution ist weggelassen, müssen die anderen Regeln für Inline-Funktionen gemäß 7.1.2 immer noch respektiert werden.
Der Compiler muss also keine Funktion "inline" einfügen.
Aber der Standard sagt auch,
Eine Inline-Funktion mit externer Verknüpfung soll in allen Übersetzungseinheiten die gleiche Adresse haben.
Elementfunktionen haben normalerweise eine externe Verknüpfung (eine Ausnahme ist, wenn die Elementfunktion zu einer 'lokalen' Klasse gehört), so dass Inline-Funktionen eine eindeutige Adresse für Fälle haben müssen, in denen die Adresse der Funktion verwendet wird. In diesem Fall wird der Compiler dafür sorgen, dass der Linker alle bis auf eine Instanz einer nicht inlinierten Kopie der Funktion entfernt und alle Adressreferenzen auf die Funktion, die zu der beibehalten wird, korrigiert.
Abschnitt [9.3], Memberfunktionen, des C ++ 98 Standards besagt:
Eine Memberfunktion kann in ihrer Klassendefinition definiert werden (8.4), in diesem Fall ist es eine inline Memberfunktion (7.1.2).
Daher war es immer so, dass die in der Klassendefinition explizit definierten Funktionen für die Elementdefinition inline
unnötig sind.
Im Funktionsbezeichner inline
gibt der Standard Folgendes an:
Eine Funktionsdeklaration (8.3.5, 9.3, 11.4) mit einem
inline
-Spezifizierer deklariert eine Inline-Funktion . Der Inline-Spezifizierer zeigt dem [C ++ - Compiler] an, dass eine Inline-Substitution des Funktionskörpers zum Zeitpunkt des Aufrufs dem üblichen Funktionsaufrufmechanismus vorzuziehen ist. [Ein C ++ - Compiler] ist jedoch nicht erforderlich, um diese Inline-Substitution bei Aufruf auszuführen;
Es liegt also am Compiler, ob es die Definition der Funktion tatsächlich inline einfügt, anstatt sie über den üblichen Funktionsaufrufmechanismus aufzurufen.
Nichts ist immer inline (es sei denn, Ihr Compiler verfügt über ein Attribut oder ein privates Schlüsselwort, um dies zu erzwingen ... zu diesem Zeitpunkt schreiben Sie $ (COMPILER) -fantasiertes C ++ statt Standard C ++). Sehr lange Funktionen, rekursive Funktionen und einige andere Dinge sind im Allgemeinen nicht inline.
Der Compiler kann festlegen, dass kein Inline-Material eingefügt wird, wenn festgestellt wird, dass dies die Leistung beeinträchtigt, die Größe der Objektdatei unangemessen erhöht oder die Funktionsweise der Objekte beeinträchtigt. Oder wenn es für die Größe statt für die Geschwindigkeit optimiert wird. Oder wenn du es fragst. Oder wenn es dein Hemd nicht mag. Oder wenn es heute faul ist, weil es letzte Nacht zu viel kompiliert hat. Oder aus irgendeinem anderen Grund. Oder ohne Grund.
Es gibt keine einzige Antwort auf diese Frage. Compiler sind intelligente Biester. Sie können die Inline-Wörter zwar gezielt verwenden, aber das bedeutet nicht, dass der Compiler die Funktion tatsächlich inline einfügt.
Inline hilft dem Entwickler bei der Optimierung. Es deutet auf den Compiler hin, dass etwas inline sein sollte, aber diese Hinweise werden heutzutage im Allgemeinen ignoriert, da Compiler die Zuweisung von Registern und die Entscheidung für Inline-Funktionen verbessern können (ein Compiler kann eine Funktion zu verschiedenen Zeiten entweder inline oder nicht inline) ). Code-Generierung auf modernen Prozessoren ist viel komplizierter als auf den deterministischeren, die üblich sind, als Ritchie C erfunden hat.
Was das Wort jetzt in C ++ bedeutet, ist, dass es mehrere identische Definitionen haben kann und in jeder Übersetzungseinheit definiert werden muss, die es verwendet. (Mit anderen Worten, Sie müssen sicherstellen, dass es inline sein kann.) Sie können eine Inline-Funktion in einer Kopfzeile ohne Probleme haben, und in einer Klassendefinition definierte Elementfunktionen sind automatisch effektiv inline.
Das heißt, ich habe früher mit einem Greenhills-Compiler gearbeitet, und er hat tatsächlich mehr meinem Willen gehorcht als dem, was er nicht befolgt hat :) .. Es liegt wirklich am Compiler.
Das Schlüsselwort inline
behandelt die C ++ - Definition einer Funktion. Der Compiler kann Objektcode, wo immer er will, inline einbinden.
Inline definierte Funktionen (zB verwenden sie das Schlüsselwort inline
), erstellen Objektcode für die Funktion in jeder Übersetzungseinheit. Diese Funktionen sind als speziell gekennzeichnet, so dass der Linker nur einen verwenden kann.
Siehe diese Antwort für genauere Informationen.
Es muss nicht inline sein, nein; Es ist genau so, als hätten Sie explizit inline
angegeben.
Wenn Sie Dieser Absatz war falsch. Ich lasse es intakt, nur gestrichen, damit die untenstehenden Kommentare noch Sinn ergeben.] inline
schreiben, versprechen Sie, dass diese Methode nicht aus Übersetzungseinheiten aufgerufen wird, in denen sie nicht definiert ist und daher interne Verknüpfung (der Linker verbindet also nicht den Verweis einer Objektdatei auf ihn mit der Definition einer anderen Objektdatei).