Auf dem Oulu ISO C ++ Standards Meeting 2016 wurde ein Vorschlag namens Inline Variables vom Normungsausschuss in C ++ 17 abgestimmt.
Was sind Inline-Variablen, wie funktionieren sie und wofür sind sie nützlich? Wie sollen Inline-Variablen deklariert, definiert und verwendet werden?
const
.inline
Schlüsselwort für Funktionen tut.inline
Wenn das Schlüsselwort auf Funktionen angewendet wird, hat es einen weiteren entscheidenden Effekt, der direkt in Variablen übersetzt wird. Eineinline
Funktion, die vermutlich in einer Header-Datei deklariert ist, führt zum Zeitpunkt der Verknüpfung nicht zu Fehlern beim "Duplizieren von Symbolen", selbst wenn der Header#include
von mehreren Übersetzungseinheiten d wird.inline
Wenn das Schlüsselwort auf Variablen angewendet wird, hat es genau das gleiche Ergebnis. Das Ende.inline
direkte Kopie ihres Codes" ist dies nur eine schwache, unverbindliche Anforderung an den Optimierer. Compiler können angeforderte Funktionen und / oder nicht kommentierte Funktionen nicht inline einbinden. Der eigentliche Zweck desinline
Schlüsselworts besteht vielmehr darin, mehrere Definitionsfehler zu umgehen.Antworten:
Der erste Satz des Vorschlags:
Der garantierte Effekt, der
inline
auf eine Funktion angewendet wird, besteht darin, dass die Funktion mit externer Verknüpfung in mehreren Übersetzungseinheiten identisch definiert werden kann. In der Praxis bedeutet dies, dass die Funktion in einem Header definiert wird, der in mehreren Übersetzungseinheiten enthalten sein kann. Der Vorschlag erweitert diese Möglichkeit auf Variablen.In der Praxis können Sie mit dem (jetzt akzeptierten) Vorschlag das
inline
Schlüsselwort verwenden, um eine externe Verknüpfungs-const
Namespace-Bereichsvariable oder ein beliebigesstatic
Klassendatenelement in einer Header-Datei zu definieren, sodass die mehreren Definitionen, die sich ergeben, wenn dieser Header enthalten ist Mit dem Linker sind mehrere Übersetzungseinheiten in Ordnung - es wird nur eine davon ausgewählt.Bis einschließlich C ++ 14 war die interne Maschinerie dafür vorhanden, um
static
Variablen in Klassenvorlagen zu unterstützen , aber es gab keine bequeme Möglichkeit, diese Maschinerie zu verwenden. Man musste auf Tricks wie zurückgreifenAb C ++ 17 kann man meiner Meinung nach nur noch schreiben
… In einer Header-Datei.
Der Vorschlag enthält den Wortlaut
… Damit das oben Genannte weiter vereinfacht werden kann
… Wie von TC in einem Kommentar zu dieser Antwort vermerkt .
Der Bezeichner
constexpr
impliziert auchinline
statische Datenelemente sowie Funktionen.Anmerkungen:
¹ Für eine Funktion
inline
hat dies auch einen Hinweis auf die Optimierung, dass der Compiler es vorziehen sollte, Aufrufe dieser Funktion durch eine direkte Ersetzung des Maschinencodes der Funktion zu ersetzen. Dieser Hinweis kann ignoriert werden.quelle
Kath::hi
) müssen nicht const sein.const
Einschränkung vollständig aufgehoben wird.static std::string const hi = "Zzzzz...";
?Inline-Variablen sind Inline-Funktionen sehr ähnlich. Es signalisiert dem Linker, dass nur eine Instanz der Variablen vorhanden sein sollte, selbst wenn die Variable in mehreren Kompilierungseinheiten angezeigt wird. Der Linker muss sicherstellen, dass keine Kopien mehr erstellt werden.
Inline-Variablen können verwendet werden, um Globals nur in Header-Bibliotheken zu definieren. Vor C ++ 17 mussten sie Problemumgehungen (Inline-Funktionen oder Template-Hacks) verwenden.
Eine Problemumgehung besteht beispielsweise darin, den Meyer-Singleton mit einer Inline-Funktion zu verwenden:
Dieser Ansatz weist einige Nachteile auf, hauptsächlich in Bezug auf die Leistung. Dieser Aufwand könnte durch Vorlagenlösungen vermieden werden, aber es ist leicht, sie falsch zu verstehen.
Mit Inline-Variablen können Sie sie direkt deklarieren (ohne einen Linker-Fehler mit mehreren Definitionen zu erhalten):
Abgesehen von Bibliotheken nur für Header gibt es andere Fälle, in denen Inline-Variablen hilfreich sein können. Nir Friedman behandelt dieses Thema in seinem Vortrag auf der CppCon: Was C ++ - Entwickler über Globals (und den Linker) wissen sollten . Der Teil über Inline-Variablen und die Problemumgehungen beginnt um 18 Uhr 9 .
Kurz gesagt, wenn Sie globale Variablen deklarieren müssen, die von Kompilierungseinheiten gemeinsam genutzt werden, ist die Deklaration als Inline-Variablen in der Header-Datei unkompliziert und vermeidet die Probleme mit Problemumgehungen vor C ++ 17.
(Es gibt immer noch Anwendungsfälle für den Meyer-Singleton, zum Beispiel, wenn Sie ausdrücklich eine verzögerte Initialisierung wünschen.)
quelle
Minimal lauffähiges Beispiel
Mit dieser fantastischen C ++ 17-Funktion können wir:
constexpr
: Wie deklariere ich constexpr extern?main.cpp
notmain.hpp
notmain.cpp
Kompilieren und ausführen:
GitHub stromaufwärts .
Siehe auch: Wie funktionieren Inline-Variablen?
C ++ - Standard für Inline-Variablen
Der C ++ - Standard garantiert, dass die Adressen gleich sind. C ++ 17 N4659 Standardentwurf 10.1.6 "Der Inline-Spezifizierer":
cppreference https://en.cppreference.com/w/cpp/language/inline erklärt, dass, wenn
static
nicht angegeben, eine externe Verknüpfung besteht.Implementierung von GCC-Inline-Variablen
Wir können beobachten, wie es implementiert wird mit:
was beinhaltet:
und
man nm
sagt überu
:Wir sehen also, dass es dafür eine dedizierte ELF-Erweiterung gibt.
Pre-C ++ 17:
extern const
Vor C ++ 17 und in C können wir mit a einen sehr ähnlichen Effekt erzielen
extern const
, der dazu führt, dass ein einzelner Speicherort verwendet wird.Die Nachteile
inline
sind:constexpr
mit dieser Technik zu erstellen, sonderninline
erlaubt nur Folgendes : Wie deklariere ich constexpr extern?main.cpp
notmain.cpp
notmain.hpp
GitHub stromaufwärts .
Nur Header-Alternativen vor C ++ 17
Diese sind nicht so gut wie die
extern
Lösung, aber sie funktionieren und belegen nur einen einzigen Speicherort:Eine
constexpr
Funktion, weilconstexpr
impliziertinline
undinline
erlaubt (erzwingt), dass die Definition auf jeder Übersetzungseinheit erscheint :und ich wette, dass jeder anständige Compiler den Aufruf einbindet.
Sie können auch eine
const
oder eineconstexpr
statische Ganzzahlvariable wie folgt verwenden:Sie können jedoch nicht die Adresse übernehmen oder sie wird odr-verwendet, siehe auch: https://en.cppreference.com/w/cpp/language/static "Konstante statische Elemente " und Definieren statischer Constexpr-Daten Mitglieder
C.
In C ist die Situation dieselbe wie in C ++ vor C ++ 17, ich habe ein Beispiel hochgeladen unter: Was bedeutet "statisch" in C?
Der einzige Unterschied besteht darin, dass in C ++ für Globale
const
impliziertstatic
wird, in C: C ++ jedoch nicht die Semantik von `static const` vs` const`Gibt es eine Möglichkeit, es vollständig zu integrieren?
TODO: Gibt es eine Möglichkeit, die Variable vollständig zu inline, ohne überhaupt Speicher zu verwenden?
Ähnlich wie der Präprozessor.
Dies würde irgendwie erfordern:
Verbunden:
Getestet in Ubuntu 18.10, GCC 8.2.0.
quelle
inline
hat fast nichts mit Inlining zu tun, weder für Funktionen noch für Variablen, trotz des Wortes selbst.inline
weist den Compiler nicht an, etwas zu inline. Es weist den Linker an, sicherzustellen, dass es nur eine Definition gibt, die traditionell die Aufgabe des Programmierers war. Also "Gibt es eine Möglichkeit, es vollständig zu integrieren?" ist zumindest eine völlig unabhängige Frage.