wake-up-neo.com

Wann sollte ich das Schlüsselwort 'inline' für eine Funktion / Methode schreiben?

Wann sollte ich das Schlüsselwort inline für eine Funktion/Methode in C++ schreiben?

Nachdem Sie einige Antworten, einige verwandte Fragen gesehen haben:

  • Wann sollte ich nicht das Schlüsselwort 'inline' für eine Funktion/Methode in C++ schreiben?

  • Wann wird der Compiler nicht wissen, wann er eine Funktion/Methode 'inline' machen soll?

  • Ist es wichtig, wenn eine Anwendung Multithreading ist, wenn man für eine Funktion/Methode 'Inline' schreibt?

500
Partial

Oh man, einer meiner Lieblingstaler.

inline ist mehr wie static oder extern als eine Anweisung, die den Compiler auffordert, Ihre Funktionen zu integrieren. extern, static, inline sind Verknüpfungsanweisungen, die fast ausschließlich vom Linker und nicht vom Compiler verwendet werden.

Es wird gesagt, dass inline dem Compiler andeutet, dass die Funktion Ihrer Meinung nach inline sein sollte. Das mag 1998 der Fall gewesen sein, aber ein Jahrzehnt später benötigt der Compiler keine derartigen Hinweise. Ganz zu schweigen davon, dass Menschen in der Regel falsch liegen, wenn es um die Optimierung von Code geht. Daher ignorieren die meisten Compiler den "Hinweis".

  • static - Der Name der Variablen/Funktion kann nicht in anderen Übersetzungseinheiten verwendet werden. Der Linker muss sicherstellen, dass er nicht versehentlich eine statisch definierte Variable/Funktion einer anderen Übersetzungseinheit verwendet.

  • extern - Verwenden Sie diesen Variablen-/Funktionsnamen in dieser Übersetzungseinheit, aber beschweren Sie sich nicht, wenn er nicht definiert ist. Der Linker wird es aussortieren und sicherstellen, dass der gesamte Code, der versucht hat, ein externes Symbol zu verwenden, seine Adresse hat.

  • inline - Diese Funktion wird in mehreren Übersetzungseinheiten definiert, keine Sorge. Der Linker muss sicherstellen, dass alle Übersetzungseinheiten eine einzige Instanz der Variablen/Funktion verwenden.

Hinweis: Die Deklaration von Vorlagen inline ist im Allgemeinen sinnlos, da sie bereits die Verknüpfungssemantik von inline haben. Die explizite Spezialisierung und Instanziierung von Vorlagen erfordert die Verwendung von inline .


Spezifische Antworten auf Ihre Fragen:

  • Wann sollte ich das Schlüsselwort 'inline' für eine Funktion/Methode in C++ schreiben?

    Nur wenn die Funktion in einer Kopfzeile definiert werden soll. Genauer gesagt nur, wenn die Definition der Funktion in mehreren Übersetzungseinheiten angezeigt werden kann. Es ist eine gute Idee, kleine (wie in einer Zeile) Funktionen in der Header-Datei zu definieren, da der Compiler dadurch mehr Informationen erhält, mit denen er arbeiten kann, während er den Code optimiert. Dies verlängert auch die Kompilierungszeit.

  • Wann sollte ich das Schlüsselwort 'inline' für eine Funktion/Methode in C++ nicht schreiben?

    Fügen Sie Inline nicht hinzu, nur weil Sie glauben, dass Ihr Code schneller ausgeführt wird, wenn der Compiler ihn einfügt.

  • Wann wird der Compiler nicht wissen, wann er eine Funktion/Methode 'inline' machen soll?

    Im Allgemeinen kann der Compiler dies besser als Sie. Der Compiler kann jedoch keinen Code einbinden, wenn er nicht über die Funktionsdefinition verfügt. Im maximal optimierten Code werden normalerweise alle private Methoden eingeblendet, ob Sie danach fragen oder nicht.

    Verwenden Sie __attribute__(( noinline )) und in Visual Studio __declspec(noinline), um Inlining in GCC zu verhindern.

  • Ist es wichtig, wenn eine Anwendung mehrere Threads ausführt, wenn eine Funktion/Methode inline geschrieben wird?

    Multithreading beeinflusst das Inlining in keiner Weise.

790
deft_code

Ich möchte zu allen großartigen Antworten in diesem Thread mit einem überzeugenden Beispiel beitragen, um verbleibende Missverständnisse zu zerstreuen.

Gegeben zwei Quelldateien, wie zum Beispiel:

  • inline111.cpp:

    #include <iostream>
    
    void bar();
    
    inline int fun() {
      return 111;
    }
    
    int main() {
      std::cout << "inline111: fun() = " << fun() << ", &fun = " << (void*) &fun;
      bar();
    }
    
  • inline222.cpp:

    #include <iostream>
    
    inline int fun() {
      return 222;
    }
    
    void bar() {
      std::cout << "inline222: fun() = " << fun() << ", &fun = " << (void*) &fun;
    }
    

  • Fall A:

    Kompilieren:

    g++ -std=c++11 inline111.cpp inline222.cpp
    

    Ausgabe:

    inline111: fun() = 111, &fun = 0x4029a0
    inline222: fun() = 111, &fun = 0x4029a0
    

    Diskussion:

    1. Auch wenn Sie identische Definitionen Ihrer Inline-Funktionen haben sollten, markiert der C++ - Compiler diese nicht, wenn dies nicht der Fall ist (tatsächlich gibt es aufgrund von separate Kompilierung keine Möglichkeiten, dies zu überprüfen). Dies zu gewährleisten, liegt in Ihrer eigenen Verantwortung!

    2. Der Linker beschwert sich nicht über One Definition Rule, da fun() als inline deklariert ist. Da jedoch inline111.cpp die erste vom Compiler verarbeitete Übersetzungseinheit ist (die tatsächlich fun() aufruft), instanziiert der Compiler fun() bei - first ​​Anrufbegegnung in inline111.cpp . Wenn der Compiler beschließt nicht , fun() bei seinem Aufruf von einer anderen Stelle in Ihrem Programm aus zu erweitern (zB von Inline222.cpp ) wird der Aufruf von fun() immer mit seiner Instanz verknüpft, die aus inline111.cpp (dem Aufruf von fun() inside inline222.cpp erzeugt möglicherweise auch eine Instanz in dieser Übersetzungseinheit, bleibt jedoch nicht verbunden). Dies ist in der Tat aus den identischen &fun = 0x4029a0 Ausdrucken ersichtlich.

    3. Schließlich, trotz des inline Vorschlags an den Compiler, tatsächlich zu erweitern den Einzeiler fun(), ignoriert ​​Ihren Vorschlag vollständig, was ist klar, weil fun() = 111 in beiden Zeilen.


  • Fall B:

    Kompilieren(umgekehrte Reihenfolge beachten):

    g++ -std=c++11 inline222.cpp inline111.cpp
    

    Ausgabe:

    inline111: fun() = 222, &fun = 0x402980
    inline222: fun() = 222, &fun = 0x402980
    

    Diskussion:

    1. In diesem Fall wird behauptet, was in Fall A besprochen wurde.

    2. Beachten Sie einen wichtigen Punkt, wenn Sie den tatsächlichen Aufruf von fun() in inline222.cpp auskommentieren (zB auskommentieren cout- Anweisung in inline222.cpp vollständig, dann wird fun() trotz der Kompilierungsreihenfolge Ihrer Übersetzungseinheiten beim ersten Aufrufen in inline111.cpp , was zu einem Ausdruck für Case B als inline111: fun() = 111, &fun = 0x402980.


  • Fall C:

    Compile(notice -O2):

    g++ -std=c++11 -O2 inline222.cpp inline111.cpp
    

    oder

    g++ -std=c++11 -O2 inline111.cpp inline222.cpp
    

    Ausgabe:

    inline111: fun() = 111, &fun = 0x402900
    inline222: fun() = 222, &fun = 0x402900
    

    Diskussion:

    1. Wie hier beschrieben , fordert die -O2 -Optimierung den Compiler auf, tatsächlich zu erweitern die Funktionen, die eingebunden werden können (Beachten Sie auch, dass -fno-inlineStandard ohne Optimierungsoptionen). Wie aus dem Ausdruck hier hervorgeht, wurde das fun() tatsächlich inline expandiert ​​(gemäß seiner Definition in dieser bestimmten Übersetzungseinheit), was zu zwei - different ​​fun() Ausdrucke. Trotzdem gibt es immer noch nur eine global verknüpfte Instanz von fun() (wie vom Standard gefordert), wie aus identisch&fun hervorgeht. ausdrucken.
47
Alaroff

Sie müssen Ihre Funktion noch explizit einbinden, wenn Sie eine Vorlagenspezialisierung durchführen (wenn sich die Spezialisierung in einer .h-Datei befindet)

27
BostonLogan

1) Heutzutage so ziemlich nie. Wenn es eine gute Idee ist, eine Funktion zu integrieren, wird der Compiler dies ohne Ihre Hilfe tun.

2) immer. Siehe # 1.

(Bearbeitet, um zu reflektieren, dass Sie Ihre Frage in zwei Fragen zerlegt haben ...)

18
Aric TenEyck

Wann sollte ich das Schlüsselwort 'inline' für eine Funktion/Methode in C++ nicht schreiben?

Wenn die Funktion in der .cpp Datei, sollten Sie nicht das Schlüsselwort schreiben.

Wann weiß der Compiler nicht, wann er eine Funktion/Methode 'inline' machen soll?

Es gibt keine solche Situation. Der Compiler kann keine Funktion inline machen. Alles, was es tun kann, ist, einige oder alle Aufrufe der Funktion inline zu schalten. Dies ist nicht möglich, wenn der Code der Funktion fehlt (in diesem Fall muss der Linker dies tun, wenn er dazu in der Lage ist).

Ist es wichtig, wenn eine Anwendung mehrere Threads ausführt, wenn eine Funktion/Methode inline geschrieben wird?

Nein, das spielt überhaupt keine Rolle.

  • Wann weiß der Compiler nicht, wann er eine Funktion/Methode 'inline' machen soll?

Dies hängt vom verwendeten Compiler ab. Vertrauen Sie nicht blindlings darauf, dass Compiler heutzutage besser als Menschen wissen, wie man inline arbeitet, und verwenden Sie es niemals aus Leistungsgründen, da es sich eher um eine Verknüpfungsrichtlinie als um einen Optimierungshinweis handelt. Obwohl ich der Meinung bin, dass diese Argumente ideologisch korrekt sind, könnte die Begegnung mit der Realität eine andere Sache sein.

Nachdem ich mehrere Threads gelesen hatte, versuchte ich aus Neugier die Auswirkungen von Inline auf den Code, an dem ich gerade arbeite, und die Ergebnisse waren, dass ich messbare Beschleunigung für GCC und keine Beschleunigung für Intel Compiler bekam.

(Weitere Details: Mathematische Simulationen mit wenigen außerhalb der Klasse definierten kritischen Funktionen, GCC 4.6.3 (g ++ -O3), ICC 13.1.0 (icpc -O3); Hinzufügen von Inline zu kritischen Punkten verursacht + 6% Geschwindigkeitssteigerung mit GCC-Code).

Wenn Sie also GCC 4.6 als modernen Compiler qualifizieren, ist die Inline-Direktive nach wie vor von Bedeutung, wenn Sie CPU-intensive Aufgaben schreiben und genau wissen, wo der Engpass liegt.

5
meda beda

In Wirklichkeit so ziemlich nie. Sie schlagen lediglich vor, dass der Compiler eine bestimmte Funktion inline ausführt (z. B. alle Aufrufe dieser Funktion mit ihrem Hauptteil ersetzen). Natürlich gibt es keine Garantie: Der Compiler kann die Direktive ignorieren.

Der Compiler kann solche Dinge im Allgemeinen gut erkennen und optimieren.

3
DarkSquid

standardmäßig integriert gcc beim Kompilieren ohne aktivierte Optimierung keine Funktionen. Ich kenne mich mit Visual Studio nicht aus - deft_code

Ich habe dies für Visual Studio 9 (15.00.30729.01) durch Kompilieren mit/FAcs und Betrachten des Assembly-Codes überprüft: Der Compiler hat Aufrufe an Member-Funktionen ohne aktivierte Optimierung im Modus Debug erzeugt. Auch wenn die Funktion mit __ forceinline markiert ist, wird kein Inline-Laufzeitcode erzeugt.

2
Jedzia

Die C++ - Inline-Funktion ist ein leistungsfähiges Konzept, das häufig für Klassen verwendet wird. Wenn eine Funktion inline ist, platziert der Compiler an jedem Punkt, an dem die Funktion zur Kompilierungszeit aufgerufen wird, eine Kopie des Codes dieser Funktion.

Jede Änderung an einer Inline-Funktion kann dazu führen, dass alle Clients der Funktion neu kompiliert werden müssen, da der Compiler den gesamten Code erneut ersetzen muss, andernfalls wird die alte Funktionalität beibehalten.

Um eine Funktion einzurichten, setzen Sie das Schlüsselwort inline vor den Funktionsnamen und definieren Sie die Funktion, bevor Sie die Funktion aufrufen. Der Compiler kann das Inline-Qualifikationsmerkmal ignorieren, wenn die definierte Funktion mehr als eine Zeile ist.

Eine Funktionsdefinition in einer Klassendefinition ist eine Inline-Funktionsdefinition, auch ohne die Verwendung des Inline-Bezeichners.

Das folgende Beispiel verwendet die Inline-Funktion, um maximal zwei Zahlen zurückzugeben

#include <iostream>

using namespace std;

inline int Max(int x, int y) { return (x > y)? x : y; }

// Main function for the program
int main() {
   cout << "Max (100,1010): " << Max(100,1010) << endl;

   return 0;
}

weitere Informationen finden Sie unter hier .

1
amirfg

Sie möchten es ganz an den Anfang stellen, bevor Sie den Rückgabetyp eingeben. Aber die meisten Compiler ignorieren es. Wenn es definiert ist und einen kleineren Codeblock enthält, wird es von den meisten Compilern ohnehin als inline betrachtet.

0
Jeremy Morgan