inline-Spezifizierer
Der inline Specifier deklariert eine Funktion als Inline-Funktion, wenn er in der decl-specifier-seq einer Funktion verwendet wird.
Eine Funktion, die vollständig innerhalb einer Klassen-/Struktur-/Union-Definition definiert ist, sei es eine Member-Funktion oder eine nicht-Member friend-Funktion, ist implizit eine Inline-Funktion es sei denn, sie ist an ein benanntes Modul angehängt(seit C++20).
|
Eine Funktion, die in ihrer ersten Deklaration als constexpr oder consteval(seit C++20) deklariert wird, ist implizit eine Inline-Funktion. Eine gelöschte Funktion ist implizit eine Inline-Funktion: Ihre (gelöschte) Definition kann in mehr als einer Translation Unit erscheinen. |
(seit C++11) |
|
Der inline Specifier deklariert eine Variable mit statischer Speicherklasse (statisches Klassen-Member oder Variable im Namensraum) als Inline-Variable, wenn er in der decl-specifier-seq verwendet wird. Ein statisches Daten-Member, das in seiner ersten Deklaration als constexpr deklariert wird, ist implizit eine Inline-Variable. |
(seit C++17) |
Inhalt |
[edit] Erklärung
Eine Inline-Funktion oder Inline-Variable(seit C++17) hat die folgenden Eigenschaften
- Die Definition einer Inline-Funktion oder Variablen(seit C++17) muss in der Translation Unit, in der sie aufgerufen wird, erreichbar sein (nicht notwendigerweise vor der Aufrufstelle).
- Eine Inline-Funktion oder Variable(seit C++17) mit externer Bindung (z.B. nicht als static deklariert) hat die folgenden zusätzlichen Eigenschaften
- Es darf mehr als eine Definition einer Inline-Funktion oder Variable(seit C++17) im Programm geben, solange jede Definition in einer anderen Translation Unit erscheint und (für nicht-statische Inline-Funktionen und Variablen(seit C++17)) alle Definitionen identisch sind. Beispielsweise kann eine Inline-Funktion oder eine Inline-Variable(seit C++17) in einer Header-Datei definiert werden, die in mehrere Quelldateien inkludiert wird.
- Sie muss in jeder Translation Unit als inline deklariert werden.
- Sie hat in jeder Translation Unit die gleiche Adresse.
Bei einer Inline-Funktion,
- Funktionslokale statische Objekte in allen Funktionsdefinitionen werden über alle Translation Units hinweg geteilt (sie beziehen sich alle auf dasselbe Objekt, das in einer Translation Unit definiert ist).
- In allen Funktionsdefinitionen definierte Typen sind ebenfalls in allen Translation Units gleich.
|
Inline-const-Variablen im Namensraum haben standardmäßig externe Bindung (im Gegensatz zu den nicht-inline und nicht-volatilen const-qualifizierten Variablen). |
(seit C++17) |
Die ursprüngliche Absicht des inline Schlüsselworts war, dem Optimierer anzuzeigen, dass die Inline-Substitution einer Funktion gegenüber dem Funktionsaufruf bevorzugt wird, d.h. anstatt die CPU-Instruktion für den Funktionsaufruf auszuführen, um die Kontrolle an den Funktionskörper zu übertragen, wird eine Kopie des Funktionskörpers ausgeführt, ohne den Aufruf zu generieren. Dies vermeidet den durch den Funktionsaufruf entstehenden Overhead (Übergabe der Argumente und Abrufen des Ergebnisses), kann aber zu einer größeren ausführbaren Datei führen, da der Code der Funktion mehrmals wiederholt werden muss.
Da die Inline-Substitution in der Standardsemantik nicht beobachtbar ist, können Compiler die Inline-Substitution für jede Funktion verwenden, die nicht als inline markiert ist, und sind frei, Funktionsaufrufe für jede als inline markierte Funktion zu generieren. Diese Optimierungsentscheidungen ändern nichts an den oben genannten Regeln bezüglich mehrfacher Definitionen und geteilter Statics.
|
Da die Bedeutung des Schlüsselworts inline für Funktionen seit C++98 eher "mehrere Definitionen sind erlaubt" als "Inlining wird bevorzugt" bedeutete, wurde diese Bedeutung auf Variablen erweitert. |
(seit C++17) |
[edit] Hinweise
Wenn eine Inline-Funktion oder Variable(seit C++17) mit externer Bindung in verschiedenen Translation Units unterschiedlich definiert wird, ist das Programm ill-formed, kein diagnostischer Fehler erforderlich.
Der inline Specifier kann nicht mit einer Funktions- oder Variablen-(seit C++17) Deklaration auf Block-Scope (innerhalb einer anderen Funktion) verwendet werden.
Der inline Specifier kann keine Funktion- oder Variable(seit C++17), die bereits in der Translation Unit als nicht-inline definiert wurde, erneut deklarieren.
Die implizit generierten Member-Funktionen und alle Member-Funktionen, die in ihrer ersten Deklaration als defaulted deklariert werden, sind wie jede andere Funktion, die innerhalb einer Klassendefinition definiert ist, inline.
Wenn eine Inline-Funktion in verschiedenen Translation Units deklariert wird, müssen die angesammelten Sätze von Standardargumenten am Ende jeder Translation Unit gleich sein.
In C müssen Inline-Funktionen nicht in jeder Translation Unit als inline deklariert werden (höchstens eine kann nicht-inline oder extern inline sein), die Funktionsdefinitionen müssen nicht identisch sein (aber das Verhalten des Programms ist undefiniert, wenn es davon abhängt, welche aufgerufen wird), und die funktionslokalen Statics sind zwischen verschiedenen Definitionen derselben Funktion unterschiedlich.
|
Weitere Regeln zu Inline-Statik-Membern finden Sie unter statische Daten-Member. Inline-Variablen beseitigen das Haupthindernis für die Verpackung von C++-Code als reine Header-Bibliotheken. |
(seit C++17) |
| Feature-Testmakro | Wert | Std | Feature |
|---|---|---|---|
__cpp_inline_variables |
201606L |
(C++17) | Inline-Variablen |
[edit] Schlüsselwörter
[edit] Beispiel
Header "example.h"
#ifndef EXAMPLE_H #define EXAMPLE_H #include <atomic> // function included in multiple source files must be inline inline int sum(int a, int b) { return a + b; } // variable with external linkage included in multiple source files must be inline inline std::atomic<int> counter(0); #endif
Quelldatei #1
#include "example.h" int a() { ++counter; return sum(1, 2); }
Quelldatei #2
#include "example.h" int b() { ++counter; return sum(3, 4); }
[edit] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| CWG 281 | C++98 | eine friend-Funktionsdeklaration könnte den inline-Specifier verwenden auch wenn die friended Funktion keine Inline-Funktion ist |
verbietet solche Verwendungen |
| CWG 317 | C++98 | eine Funktion könnte inline deklariert werden, auch wenn sie eine nicht-inline Definition in derselben Translation Unit vor der Deklaration hat |
das Programm ist schlecht ge- formt in diesem Fall |
| CWG 765 | C++98 | ein in einer Inline-Funktion definierter Typ könnte in verschiedenen Translation Units unterschiedlich sein |
solche Typen sind gleich in allen Translation Units |
| CWG 1823 | C++98 | String-Literale in allen Definitionen einer Inline- Funktion wurden über alle Translation Units hinweg geteilt |
die Anforderung wird aufgrund von Konsistenz und Implementierungen entfernt |
| CWG 2531 | C++17 | ein statisches Daten-Member könnte implizit inline sein, auch wenn es bei seiner ersten Deklaration nicht als constexpr deklariert wurde |
es ist in diesem Fall nicht implizit inline |
[edit] Siehe auch
| C-Dokumentation für inline
|