C ++ Inline-Funktion?

73

Warum sollte ich so etwas tun:

inline double square (double x) { return x*x;}

anstatt

double square (double x) { return x*x;}

Ist da ein Unterschied?

Pwnna
quelle
Mögliches Duplikat von Inline-Funktionen gegen Präprozessor-Makros
Steve Jessop
1
Tatsächlich gibt es viele Dupes und Near- Dupes : stackoverflow.com/search?q=c%2B%2B+inline . Einige der Antworten sind besser als andere, andere geben fälschlicherweise an, dass das inlineSchlüsselwort bewirkt, dass die Funktion an allen Anrufstellen eingebunden wird, und so weiter. Das ist vielleicht nicht der nächste Betrüger.
Steve Jessop
Siehe auch Inline-Funktionen in den C ++ - FAQ. Sie haben eine sehr gute Behandlung von Inline.
JWW

Antworten:

86

Ersteres (Verwenden inline) ermöglicht es Ihnen, diese Funktion in eine Header-Datei einzufügen, wo sie in mehreren Quelldateien enthalten sein kann. Mit using inlinewird der Bezeichner im Dateibereich erstellt , ähnlich wie beim Deklarieren static. Ohne Verwendung inlinewürde der Linker einen Fehler bei der Definition mehrerer Symbole erhalten.

Dies ist natürlich zusätzlich zu dem Hinweis an den Compiler, dass die Funktion inline kompiliert werden sollte, wo sie verwendet wird (Vermeidung eines Overheads für Funktionsaufrufe). Der Compiler muss nicht auf den inlineHinweis reagieren.

Greg Hewgill
quelle
1
Ich dachte, der Zweck von Inline ist, dass der Compiler den Inhalt der Funktion, in der er aufgerufen wird, "erweitert", damit keine vtable-Suche erfolgt (oder ein Befehlssprung zur Funktion auf CPU-Ebene erfolgt).
DJ.
Ist Ihr erster Punkt eine [nützliche] Nebenwirkung des beabsichtigten Zwecks?
Ian Fleeton
@ Ian Fleeton: Es ist in der Tat eine Nebenwirkung; Wenn ein Inline-Bezeichner keinen Dateibereich hätte, wäre es unmöglich, überhaupt eine Inline-Funktionsdefinition in eine Header-Datei einzufügen.
Greg Hewgill
10
@ Greg: Es verhält sich nicht wirklich so wie es war static. In diesem Fall hätte jede Übersetzungseinheit ihr eigenes Eigentum an ihrer Kopie der Funktion, und der Linker würde sie alle als unterschiedliche Funktionen behandeln (die zufällig denselben Namen hatten). Im Gegensatz dazu inlineweist der Linker an, dass, falls unterschiedliche Definitionen dieser Funktion angezeigt werden, diese alle gleich sind und zu einer zusammengeführt werden müssen. Aber wenn man dieses Detail ignoriert, verhält es sich größtenteils so, als wäre es so static.
GManNickG
1
@DJ: inlinekann die vtable-Suche nicht verhindern, dafür müssen Sie die Devirtualisierung aufrufen .
Ben Voigt
26

Ja, da gibt es einen Unterschied. https://isocpp.org/wiki/faq/inline-functions .

Wenn Sie angeben, dass eine Funktion inline ist, veranlasst der Compiler, den Code der Methode dort abzulegen, wo sie aufgerufen wird.

void myfunc() {
  square(2);
}

ist identisch mit

void myfunc() {
   2 * 2;
}

Das Aufrufen einer Funktion ist gut für die Klarheit des Codes, aber wenn diese Funktion aufgerufen wird, muss der lokale Status auf den Stapel verschoben werden, ein neuer lokaler Status wird für die Methode eingerichtet, und wenn dies erledigt ist, muss der vorherige Status gelöscht werden. Das ist viel Aufwand.

Wenn Sie jetzt Ihre Optimierungsstufe erhöhen, trifft der Compiler Entscheidungen wie das Abrollen von Schleifen oder Inlining-Funktionen. Dem Compiler steht es weiterhin frei, die Inline-Anweisung zu ignorieren.

Erik Nedwidek
quelle
2
Ich denke, mit gcc können Sie das Kompilierungsflag verwenden -Winline, um zu warnen, wenn eine Funktion nicht inline ist. Und Sie könnten das kombinieren, -Werrorwenn Sie ein Massochist sind.
Patmanpato
"Der Compiler kann die Inline-Anweisung weiterhin ignorieren." Tatsächlich tut dies jeder moderne Compiler.
Val sagt Reinstate Monica
25

Auf einem modernen Compiler gibt es wahrscheinlich keinen großen Unterschied. Es kann ohne die inline sein , inlineund es kann nicht inline sein , mit der inline.

Ben Jackson
quelle
Sinnvoll, ich ging von Referenz und 10-jähriger Erfahrung.
Ian Fleeton
5

Aus Wikipedia: Die Inline-Funktion ist eine Funktion, für die der Compiler aufgefordert wurde, eine Inline-Erweiterung durchzuführen. Mit anderen Worten, der Programmierer hat den Compiler aufgefordert, an jeder Stelle, an der die Funktion aufgerufen wird, den gesamten Funktionskörper einzufügen, anstatt Code zu generieren, um die Funktion an der Stelle aufzurufen, an der sie definiert ist. Compiler sind nicht verpflichtet, diese Anfrage zu respektieren.

http://en.wikipedia.org/wiki/Inline_function

johannesMatevosyan
quelle
2

inlinefunktioniert gut mit dem Konzept der prozeduralen Abstraktion :

inline double square (double x) { return x*x;}

int squareTwice(double x) {
    double first = square(x);
    double second = square(x);
    return first * second; 
}

Das Obige ähnelt im Wesentlichen dem Folgenden:

int squareTwice(double x) {
    double first = x*x;
    double second = x*x;
    return first * second; 
}

Dies liegt daran, dass beim Inline-Erweitern eines Funktionsaufrufs durch den Compiler der Funktionscode in den Codestream des Aufrufers eingefügt wird. Daher kann es einfacher sein, das zweite Beispiel prozedural zum ersten Beispiel zu abstrahieren.

Die prozedurale Abstraktion ermöglicht es, eine Routine in kleinere Unterroutinen aufzuteilen, die viel einfacher zu lesen sind (obwohl dies eine Stilwahl sein kann).

Gio Borje
quelle
1

Wenn der Compiler die Anforderungen erfüllt, wird die Inline-Funktion die Inline-Funktion in den Code aufnehmen, in dem sie aufgerufen wurde, als ob keine Funktion aufgerufen worden wäre (als hätten Sie die Logik in die aufrufende Funktion eingefügt), und den Overhead des Funktionsaufrufs vermeiden.

Ian Fleeton
quelle
6
Der Compiler muss die Funktion nicht einbinden, wenn er dies nicht möchte, selbst wenn das Schlüsselwort inline angegeben ist.
Marlon
1
@Alex Marlon hat nicht gesagt, dass der Compiler die Funktion nicht einbinden würde, sondern nur, dass dies nicht erforderlich ist . Das sind sehr unterschiedliche Dinge.
Michael Dorst