Das Vermeiden der Kosten eines Funktionsaufrufs ist nur die halbe Wahrheit.
machen:
- verwenden
inline
statt#define
- Sehr kleine Funktionen sind gute Kandidaten für
inline
: schnelleren Code und kleinere ausführbare Dateien (mehr Chancen, im Code-Cache zu bleiben)
- Die Funktion ist klein und wird sehr oft aufgerufen
nicht:
- Große Funktionen: Führt zu größeren ausführbaren Dateien, was die Leistung erheblich beeinträchtigt, unabhängig von der schnelleren Ausführung, die sich aus dem Aufrufaufwand ergibt
- Inline-Funktionen, die an E / A gebunden sind
- Die Funktion wird selten verwendet
- Konstruktoren und Destruktoren: Auch wenn der Compiler leer ist, generiert er Code für sie
- Unterbrechen der Binärkompatibilität bei der Entwicklung von Bibliotheken:
- Inline eine vorhandene Funktion
- Ändern Sie eine Inline-Funktion oder machen Sie eine Inline-Funktion nicht inline: In einer früheren Version der Bibliothek wird die alte Implementierung aufgerufen
Wenn Sie eine Bibliothek entwickeln, sollten Sie Folgendes tun, um eine Klasse in Zukunft erweiterbar zu machen:
- Fügen Sie einen virtuellen Inline-Destruktor hinzu, auch wenn der Körper leer ist
- Machen Sie alle Konstruktoren nicht inline
- Schreiben Sie Nicht-Inline-Implementierungen des Kopierkonstruktors und des Zuweisungsoperators, es sei denn, die Klasse kann nicht nach Wert kopiert werden
Denken Sie daran, dass das inline
Schlüsselwort ein Hinweis für den Compiler ist: Der Compiler kann entscheiden, eine Funktion nicht zu inlineieren, und er kann entscheiden, Funktionen inline zu setzen, die überhaupt nicht markiert wurden inline
. Ich vermeide generell Markierungsfunktionen inline
(abgesehen davon, wenn ich sehr, sehr kleine Funktionen schreibe).
In Bezug auf die Leistung besteht der kluge Ansatz (wie immer) darin, die Anwendung zu profilieren und schließlich inline
eine Reihe von Funktionen, die einen Engpass darstellen.
Verweise:
EDIT: Bjarne Stroustrup, Die C ++ - Programmiersprache:
Eine Funktion kann als definiert werden inline
. Beispielsweise:
inline int fac(int n)
{
return (n < 2) ? 1 : n * fac(n-1);
}
Der inline
Bezeichner ist ein Hinweis für den Compiler, dass er versuchen sollte, Code für einen fac()
Inline- Aufruf zu generieren, anstatt den Code für die Funktion einmal festzulegen und dann über den üblichen Funktionsaufrufmechanismus aufzurufen. Ein cleverer Compiler kann die Konstante 720
für einen Aufruf generieren fac(6)
. Die Möglichkeit von gegenseitig rekursiven Inline-Funktionen, Inline-Funktionen, die je nach Eingabe rekursiv sind oder nicht, macht es unmöglich zu garantieren, dass jeder Aufruf einer inline
Funktion tatsächlich inline ist. Der Grad der Klugheit eines Compilers kann nicht gesetzlich festgelegt werden, sodass ein Compiler möglicherweise einen 720
anderen 6 * fac(5)
und einen weiteren einen nicht inlinierten Aufruf generiert fac(6)
.
Um Inlining ohne ungewöhnlich clevere Kompilierungs- und Verknüpfungsfunktionen zu ermöglichen, muss die Definition - und nicht nur die Deklaration - einer Inline-Funktion im Geltungsbereich liegen (§9.2). Ein inline
Especifier hat keinen Einfluss auf die Semantik einer Funktion. Insbesondere hat eine Inline-Funktion immer noch eine eindeutige Adresse, ebenso wie static
Variablen (§7.1.2) einer Inline-Funktion.
EDIT2: ISO-IEC 14882-1998, 7.1.2 Funktionsspezifizierer
Eine Funktionsdeklaration (8.3.5, 9.3, 11.4) mit einem Bezeichner inline
deklariert eine Inline-Funktion. Der Inline-Spezifizierer gibt der Implementierung an, dass die Inline-Substitution des Funktionskörpers am Aufrufpunkt dem üblichen Funktionsaufrufmechanismus vorzuziehen ist. Eine Implementierung ist nicht erforderlich, um diese Inline-Ersetzung am Aufrufpunkt durchzuführen. Selbst wenn diese Inline-Ersetzung weggelassen wird, bleiben die anderen in 7.1.2 definierten Regeln für Inline-Funktionen ein.
inline
ist für den C ++ - Neuling das, wasCFLAGS
für den Gentoo-Neuling ist: Nein, das Kompilieren mit-O3 -funroll-loops -finline-functions
bringt Ihren alten Pentium nicht zum Fliegen;)