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?
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?
inline
Schlüsselwort bewirkt, dass die Funktion an allen Anrufstellen eingebunden wird, und so weiter. Das ist vielleicht nicht der nächste Betrüger.
Antworten:
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 inline
wird der Bezeichner im Dateibereich erstellt , ähnlich wie beim Deklarieren static
. Ohne Verwendung inline
wü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 inline
Hinweis reagieren.
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 inline
weist 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
.
inline
kann die vtable-Suche nicht verhindern, dafür müssen Sie die Devirtualisierung aufrufen .
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.
-Winline
, um zu warnen, wenn eine Funktion nicht inline ist. Und Sie könnten das kombinieren, -Werror
wenn Sie ein Massochist sind.
Auf einem modernen Compiler gibt es wahrscheinlich keinen großen Unterschied. Es kann ohne die inline sein , inline
und es kann nicht inline sein , mit der inline
.
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.
inline
funktioniert 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).
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.