Einführung
inline-Funktionen
inline-Memberfunktionen
Einschränkungen bei inline
In dieser Lektion werden wir einmal etwas für die Laufzeit-Optimierung einer Anwendung tun.
Um auf die geschützten Eigenschaften einer Klasse zugreifen zu können, muss ja eine entsprechende Memberfunktion aufgerufen werden. Bei kurzen Memberfunktionen, die z.B. nur eine Eigenschaft setzen oder zurückliefern, wird dabei aber mehr Zeit für den Aufruf benötigt als für das Setzen oder Lesen der Eigenschaft. Nachfolgend sehen Sie einmal die Aktionen, die beim Aufruf einer Memberfunktion durchgeführt werden. Dabei haben die Aktionen 1,2,3,5 und 6 nichts direkt mit der gewünschten Funktionalität zu tun. Man bezeichnet dieses auch als Overhead. Nur die Aktionen 4 und 7 sind eigentlich notwendig um das gewünschte Ergebnis zu erhalten. Und um diesen Overhead zur vermeiden, wurden die so genannten inline-Funktionen bzw. inline-Memberfunktionen eingeführt.
|
Sehen wir uns zunächst die inline-Funktionen an. Inline-Funktionen werden prinzipiell genauso definiert wie 'normale' Funktionen. Zusätzlich wird nun aber vor dem Returntyp der Funktion das Schlüsselwort inline gestellt.
|
inline void CheckError(int err, char* pT) { if (err) { cout << "Fehler: " << err << pT << endl; exit (err); } } |
Triff der Compiler dann beim Übersetzen auf den Aufruf einer inline-Funktion, so wird anstelle des Funktionsaufrufs direkt der Code der Funktion eingefügt. Und somit entfällt der komplette Overhead für den Aufruf. Im Beispiel ist als Kommentar dargestellt, wie der Compiler den Funktionsaufruf der inline-Funktion CheckError(...) ersetzt.
|
// Inline-Funktion definieren inline void CheckError (int err, char* pT) { ... // Code siehe oben } int main() { ... CheckError(status,"Überlauf"); // Wird durch den Compiler erweitert zu: // if (status) // { // cout << "Fehler << status << "Überlauf" << endl; // } ... } |
Da nun anstelle des Funktionsaufrufs direkt der Funktionscode ins übersetzte Programm eingefügt wird, empfiehlt es sich, nur kurze Funktionen als inline-Funktionen zu definieren, da ansonsten die Größe des übersetzten Programms unter Umständen beträchtlich anwachsen kann.
|
|
Werden Memberfunktionen innerhalb einer Klasse definiert, so sind sie unter gewissen Einschränkungen (folgen gleich noch) defaultmäßig als inline-Memberfunktion definiert. Beachten Sie dies bitte, wenn Sie Memberfunktionen innerhalb einer Klasse definieren. Sie sollten dies wirklich nur für sehr kurze Memberfunktionen tun.
|
// Klassendefinition class Window { string title; ... public: // defaultmässig inline-Memberfunktion! const string& GetTitle() const { return title; } ... }; // main() Funktion int main() { Window myWin; ... cout << myWin.GetTitle() << endl; // wird compiliert zu: // cout << myWin.title << endl; ... } |
Wird eine Memberfunktion innerhalb einer Klasse nur deklariert, so kann sie bei ihrer Definition außerhalb der Klasse durch voranstellen des Schlüsselworts inline vor dem Returntyp ebenfalls als inline-Memberfunktion definiert werden. Und auch hier gelten ebenfalls Einschränkungen die gleich noch aufgeführt werden.
|
// Klassendefinition class Window { string title; ... public: const string& GetTitle() const; ... }; // inline Definition inline const string& Win::GetTitle() const { return title; } |
|
|
Wie bereits mehrfach erwähnt, bestehen bei inline-Funktionen bzw. Memberfunktionen gewisse Einschränkungen. So sind z.B. rekursive Funktionen (das sind Funktionen die sich selbst aufrufen) in der Regel nicht als inline-Funktionen zugelassen. Auch schließen einige Compiler bestimmte Anweisungen innerhalb von inline-Funktionen aus. Beim BORLAND-Compiler waren dies fast alle Anweisungen, die irgendwelche Sprünge verursachen wie z.B. Schleifen. Enthält eine inline-Memberfunktion eine nicht zugelassene Anweisung, so wird die Funktion bzw. Memberfunktion nicht als inline betrachtet.
Womit wir auch schon beim nächsten und wichtigsten Punkt wären. Die Definition einer Memberfunktion als inline ist nur eine Bitte an den Compiler, die Funktion/Memberfunktion entsprechend einzubauen und keine zwingende Vorschrift.
Und zum Schluss ist noch anzumerken, dass moderne Compiler versuchen den Code eines Moduls so gut wie möglich zu optimieren. Und dazu gehört teilweise die eigenständige Definition einer Funktion als inline-Funktion wenn sie im gleichen Modul (CPP-Datei) verwendet wird. Aber wie so oft lässt sich auch hierbei sehr viel über entsprechende Einstellungen des Compilers einstellen. Da hilft nur ein Blick ins Handbuch bzw. in die Online-Hilfe.