Heim >Backend-Entwicklung >C++ >Inline-Funktionen in C und C++

Inline-Funktionen in C und C++

PHPz
PHPzOriginal
2024-09-09 10:33:46935Durchsuche

Inline Functions in C and C++

Einführung

C++ hat das Inline-Schlüsselwort hinzugefügt, das einer Funktionsdefinition vorangestellt werden kann, wie zum Beispiel:

inline int max_int( int a, int b ) {
    return a > b ? a : b;
}

um dem Compiler einen „Hinweis“ zu geben, dass das Programm insgesamt von der Leistung profitieren könnte, wenn die Funktion inlined ist.

Bei einer Funktion, die inline wurde, wurde der Code an jedem Punkt, an dem sie aufgerufen wurde, erweitert, anstatt den normalen Funktionsaufrufmechanismus wie folgt auszuführen:

  • Register speichern.
  • Argumentwerte auf den Stapel verschieben.
  • Ausführen der Anrufanweisung.
  • Die Funktion, die schließlich die ret-Anweisung ausführt.
  • Register werden wiederhergestellt.

Bei sehr kleinen Funktionen kann Inlining zu einer Leistungssteigerung führen. Aber wie bei fast allem anderen gibt es auch hier Kompromisse.

Das Inline-Schlüsselwort wurde auf C99 zurückportiert, jedoch mit etwas anderen Anforderungen – mehr später.

Unterschiede zu Makros

Inline-Funktionen sind wie funktionsähnliche Makros (und sollen viele ihrer Anwendungen ersetzen). Im Allgemeinen ist dies eine gute Sache, denn Inline-Funktionen sind Funktionen und verfügen über eine vollständige Funktionssemantik und nicht nur über eine bloße Textersetzung durch den Präprozessor, der weder C noch C++ versteht.

Ein naiv äquivalentes Makro zur Funktion max_int():

#define MAX_INT(A,B)  A > B ? A : B  /* bad implementation */

hat folgende Probleme:

  • Erweiterte Argumente, z. B. MAX(n & 0xFF, 8), können zu einer falschen Operatorpriorität führen.
  • Argumente mit Nebenwirkungen, z. B. MAX(n++, 8), können mehrere Nebenwirkungen haben.
  • Bei der Definition findet keine Typprüfung der Argumente statt.
  • Fehler sind oft ausführlich und schwer zu lesen.

Zusätzlich ein Makro:

  • Kann sein Argument ändern (das ist oft nicht das, was Sie wollen).

Inline-Funktionen weisen keines dieser Probleme auf, können jedoch den gleichen Leistungsvorteil erzielen. Verwenden Sie daher Inline-Funktionen anstelle von funktionsähnlichen Makros.

Nur ein Hinweis

Wie bereits erwähnt ist die Angabe von „inline“ nur ein „Hinweis“ für den Compiler, dass die Leistung des Programms insgesamt von der Inline-Funktion profitieren könnte. Dem Compiler steht es frei, den Hinweis zu ignorieren.

Warum? Denn es gibt Fälle, in denen es entweder keine gute Idee oder unmöglich ist. Eine Funktion ist entweder nicht inline oder normalerweise nicht inline, wenn eine der folgenden Bedingungen zutrifft:

  • Die Funktion ist „zu groß“.
  • Sie rufen die Funktion über einen Zeiger auf die Funktion auf.
  • Die Funktion ist rekursiv.
  • Die Funktion hat eine Schleife.

Es kann andere Gründe geben. Es hängt alles stark von der Funktion, ihren Argumenten, dem Compiler und den ihr gegebenen Optionen ab.

Wenn der Compiler eine Funktion entweder nicht einbinden kann oder sich dafür entscheidet, nicht Sie zu warnen, dass er dies nicht getan hat (standardmäßig). Einige Compiler, z. B. gcc, verfügen über die Option -Winline, die Sie warnt und den Grund angibt, warum eine Funktion nicht eingebunden wurde.

Die Angabe von „inline“ ähnelt der Angabe von „register“ in älterem Code – es handelt sich bei beiden nur um Hinweise.

Wann (und wann nicht) für Inline

Bei den meisten Funktionen liegt der Großteil der Kosten für die Ausführung der Funktion im Funktionskörper und nicht im Funktionsaufrufmechanismus. Damit eine Funktion ein guter Kandidat für das Inlining ist, muss sie im Allgemeinen wie folgt sein:

  • Klein genug, damit die Kosten des Funktionsaufrufmechanismus dominieren.
  • Wird an Orten verwendet, an denen es wirklich auf die Leistung ankommt, z. B. in engen Schleifen.

Im Zweifelsfall profilieren Sie Ihren Code. Die Verwendung von Inline ist kein ein magisches „Mach mich schneller“-Schlüsselwort. Darüber hinaus kann eine übermäßige Verwendung von Inline zu einer Code-Aufblähung führen, die die Leistung Ihres Programms zusätzlich schlechter insgesamt macht.

Weitere Informationen finden Sie unter Die Inline-Krankheit.

Zu den Funktionen, die oft gute Kandidaten für das Inlining sind, gehören:

  • „Einzeiler“ wie „Getter“ und „Setter“.
  • Einfache Wrapper um Aufrufe anderer Funktionen, die bestimmte Werte für Argumente bereitstellen oder Umwandlungen durchführen.

Eine ideale Inline-Funktion beide erhöht die Leistung und verringert die Codegröße.

Eine Einschränkung für jede Inline-Funktion besteht jedoch darin, dass bei einer Änderung ihrer Definition der gesamte Code, der sie verwendet, neu kompiliert werden muss.

Inline-Optimierungen

Wenn eine Inline-Funktion tatsächlich vom Compiler eingebunden wird, kann der Compiler zusätzlich zum Weglassen des Codes für den normalen Funktionsaufrufmechanismus möglicherweise auch Folgendes tun:

  • Eliminate one or more function arguments completely whose values are constants via immediate addressing.
  • Perform better optimizations spanning the code the function is inlined into that it normally couldn’t perform across function boundaries.

Inline Function Definition

In order for the compiler to be able to inline a function, it has to be able to “see” its definition (not just its declaration) in every .c or .cpp file it’s used in just like a macro. Hence, an inline function must be defined in a header file.

Normally, a function, like everything else, must have exactly one definition by adhering to the one definition rule (ODR). However, since the definition of an inline function is “seen” in multiple .c or .cpp files, the ODR is suspended for that function.

It is possible to have different definitions for inline functions having the same name, but this results in undefined behavior since the compiler has no way to check that every definition is the same.

To inline a function in C++, all you need do is prefix the function definition with inline — that’s it. The compiler and/or linker will automatically discard all but one definition from the final executable file for you.

However, to inline a function in C, you additionally must explicitly tell the compiler into what .o file to put the one definition in the event the compiler is either unable or unwilling to inline a function via extern inline.

For example, in exactly one .c file, you would declare a function like:

// util.c
extern inline int max_int( int, int );

That tells the compiler to “put the one definition for max_int() into util.o.”

Alternatively in C, you can instead declare an inline function static also:

static inline int max_int( int a, int b ) {
    return a > b ? a : b;
}

If you do this, then:

  • You do not have to declare a function extern inline anywhere.
  • However, if the compiler doesn’t inline a function, it will generate a definition in every .c file it’s included into again leading to code bloat.
  • If the function has any static local variables, every definition will have distinct copies (that may or may not be what you want).

Conclusion

Inline functions, if used judiciously, can yield performance gains. Generally, only very small functions are good candidates for inlining.

Starting in C++11, inline functions can alternatively be declared constexpr, but that’s a story for another time.

References

  • Linux kernel coding style, §15 The inline disease.
  • Myth and reality about inline in C99.
  • The Annotated C++ Reference Manual, Margaret A. Ellis & Bjarne Stroustrup, Addison-Wesley, 1990, ISBN 0-201-51459-1, §7.1.2 Function Specifiers, pp. 99–105.

Das obige ist der detaillierte Inhalt vonInline-Funktionen in C und C++. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn