Hinweis: Hier geht es nicht darum, wie Inline-Funktionen verwendet werden oder wie sie funktionieren, sondern darum, warum sie so ausgeführt werden, wie sie sind.
Die Deklaration einer Klassenmitgliedsfunktion muss keine Funktion als definieren inline
, sondern ist nur die tatsächliche Implementierung der Funktion. Zum Beispiel in der Header-Datei:
struct foo{
void bar(); // no need to define this as inline
}
Warum also die Inline - Implementierung eines Klassen funktionieren müssen , um in der Header - Datei? Warum kann ich die Inline-Funktion nicht in die .cpp
Datei einfügen? Wenn ich versuchen würde, die Inline-Definition in die .cpp
Datei einzufügen, würde ich einen Fehler in der Art von: erhalten.
error LNK2019: unresolved external symbol
"public: void __thiscall foo::bar(void)"
(?bar@foo@@QAEXXZ) referenced in function _main
1>C:\Users\Me\Documents\Visual Studio 2012\Projects\inline\Debug\inline.exe
: fatal error LNK1120: 1 unresolved externals
inline
eine Definition angezeigt wird, aber keine vorherige Erklärung, und umgekehrt . Wenn ja, kann dies helfen: stackoverflow.com/questions/4924912/…Antworten:
Die Definition einer
inline
Funktion muss nicht in einer Header-Datei enthalten sein, sondern aufgrund der One Definition Rule ( ODR ). für Inline-Funktionen muss jedoch in jeder Übersetzungseinheit, die sie verwendet, eine identische Definition für die Funktion vorhanden sein.Der einfachste Weg, dies zu erreichen, besteht darin, die Definition in eine Header-Datei einzufügen.
Wenn Sie die Definition einer Funktion in eine einzelne Quelldatei einfügen möchten, sollten Sie sie nicht deklarieren
inline
. Eine nicht deklarierte Funktioninline
bedeutet nicht, dass der Compiler die Funktion nicht einbinden kann.Ob Sie eine Funktion deklarieren sollten
inline
oder nicht, ist normalerweise eine Entscheidung, die Sie treffen sollten, basierend auf der Version der Regeln für eine Definition , deren Befolgung für Sie am sinnvollsten ist. Das Hinzufügeninline
und anschließende Einschränken durch die nachfolgenden Einschränkungen ist wenig sinnvoll.quelle
+1
von mir!Es gibt zwei Möglichkeiten, es zu betrachten:
Inline-Funktionen werden im Header definiert, da der Compiler in der Lage sein muss, den Funktionskörper zu sehen, um einen Funktionsaufruf inline zu machen. Damit ein naiver Compiler dies tun kann, muss sich der Funktionskörper in derselben Übersetzungseinheit wie der Aufruf befinden. (Ein moderner Compiler kann über mehrere Übersetzungseinheiten hinweg optimieren. Daher kann ein Funktionsaufruf eingefügt werden, obwohl sich die Funktionsdefinition in einer separaten Übersetzungseinheit befindet. Diese Optimierungen sind jedoch teuer, nicht immer aktiviert und wurden von der nicht immer unterstützt Compiler)
Im Header definierte Funktionen müssen markiert werden,
inline
da andernfalls jede Übersetzungseinheit, die den Header enthält, eine Definition der Funktion enthält und der Linker sich über mehrere Definitionen beschwert (ein Verstoß gegen die One Definition Rule). Dasinline
Schlüsselwort unterdrückt dies, sodass mehrere Übersetzungseinheiten (identische) Definitionen enthalten können.Die beiden Erklärungen laufen wirklich darauf hinaus, dass das
inline
Schlüsselwort nicht genau das tut, was Sie erwarten würden.Ein C ++ - Compiler kann die Inlining- Optimierung (einen Funktionsaufruf durch den Hauptteil der aufgerufenen Funktion ersetzen , den Aufrufaufwand sparen) jederzeit anwenden , sofern dies das beobachtbare Verhalten des Programms nicht verändert.
Das
inline
Schlüsselwort macht es einfacher für den Compiler diese Optimierung anzuwenden, um die Funktionsdefinition ermöglicht in mehreren Übersetzungseinheiten sichtbar zu sein, aber das Schlüsselwort bedeutet nicht , den Compiler hat die Funktion inline, und nicht das Schlüsselwort nicht Verbieten Sie dem Compiler, die Funktion einzuschleusen.quelle
Dies ist eine Grenze des C ++ - Compilers. Wenn Sie die Funktion in den Header einfügen, können alle CPP-Dateien, in die sie eingefügt werden können, die "Quelle" Ihrer Funktion sehen, und das Inlining kann vom Compiler durchgeführt werden. Andernfalls müsste das Inlining vom Linker durchgeführt werden (jede cpp-Datei wird separat in einer obj-Datei kompiliert). Das Problem ist, dass es viel schwieriger wäre, dies im Linker zu tun. Ein ähnliches Problem besteht bei "Vorlagen" -Klassen / -Funktionen. Sie müssen vom Compiler instanziiert werden, da der Linker Probleme haben würde, sie zu instanziieren (eine spezielle Version davon zu erstellen). Einige neuere Compiler / Linker können eine Kompilierung / Verknüpfung mit zwei Durchgängen durchführen, wobei der Compiler einen ersten Durchgang ausführt. Dann erledigt der Linker seine Arbeit und ruft den Compiler auf, um ungelöste Probleme zu lösen (Inline / Vorlagen ...).
quelle
Der Grund ist, dass der Compiler die Definition tatsächlich sehen muss, um sie anstelle des Aufrufs ablegen zu können.
Denken Sie daran, dass C und C ++ ein sehr vereinfachtes Kompilierungsmodell verwenden, bei dem der Compiler immer nur eine Übersetzungseinheit gleichzeitig sieht. (Dies schlägt beim Export fehl. Dies ist der Hauptgrund, warum nur ein Anbieter es tatsächlich implementiert hat.)
quelle
Das
inline
Schlüsselwort c ++ ist irreführend und bedeutet nicht "Inline dieser Funktion". Wenn eine Funktion als Inline definiert ist, bedeutet dies einfach, dass sie mehrmals definiert werden kann, solange alle Definitionen gleich sind. Es ist völlig legal, dass eine Funktioninline
als echte Funktion markiert ist, die aufgerufen wird, anstatt an der Stelle, an der sie aufgerufen wird, Code inline zu setzen.Das Definieren einer Funktion in einer Header-Datei ist für Vorlagen erforderlich, da beispielsweise eine Vorlagenklasse keine Klasse ist, sondern eine Vorlage für eine Klasse, von der Sie mehrere Variationen vornehmen können. Damit der Compiler zB eine
Foo<int>::bar()
Funktion erstellen kann, wenn Sie die Foo-Vorlage zum Erstellen einer Foo-Klasse verwenden , muss die tatsächliche Definition vonFoo<T>::bar()
sichtbar sein.quelle
inline
(und wenn Sie sie nicht deklariereninline
, wird nicht garantiert, dass sie nicht inline ist).Ich weiß, dass dies ein alter Thread ist, dachte aber, ich sollte das
extern
Schlüsselwort erwähnen . Ich bin kürzlich auf dieses Problem gestoßen und habe es wie folgt gelöstHelper.h
Helper.cpp
quelle
Weil der Compiler sie sehen muss, um sie inline zu machen. Und Header-Dateien sind die "Komponenten", die üblicherweise in anderen Übersetzungseinheiten enthalten sind.
quelle
Inline-Funktionen
In C ++ ist ein Makro nichts anderes als eine Inline-Funktion. Jetzt haben Makros die Kontrolle über den Compiler.
Die Code of Inline-Funktion wird an der Stelle ersetzt, an der sie aufgerufen wird, wodurch der Overhead der aufrufenden Funktion verringert wird.
In einigen Fällen kann das Inlining der Funktion nicht funktionieren, wie z
Wenn statische Variable innerhalb der Inline-Funktion verwendet wird.
Wenn die Funktion kompliziert ist.
Bei rekursivem Funktionsaufruf
Wenn die Adresse der Funktion implizit oder explizit übernommen wurde
Funktionen, die außerhalb der Klasse wie folgt definiert sind, können inline werden
Innerhalb der Klasse definierte Funktionen werden ebenfalls inline
Hier werden sowohl die Funktionen getSpeed als auch setSpeed inline
quelle