Inline Funktionen oder besser ausgelagert?



  • Zoidberg schrieb:

    Nur mehr Code beim Gleichzeitigen Einsparen eines Aufrufs? Dann ist es doch eigentlich sinnvoller, direkt alles in die Header zu schreiben. Mehr Code ist doch nciht so schlimm.

    Inline ist aber nur ein Vorschlag an den Compiler. Ob er's macht ist seine Entscheidung.
    Kurt



  • Theoretisch könnte ich tatsächlich ein Programm schreiben, welches nur aus Headern besteht. Ich könnte auch auf so viele andere Sprachfeatures wie Schleifen (kann man durch goto ersetzen) oder Klassen (struct oder einfach mehrere Variable gehen auch). Da geht aber sehr viel verloren. Die Programme werden unleserlich und unwartbar. Ganz zu schweigen von immensen Compile-zeiten.

    Inline-Funktionen und -Methoden sollten in der Regel Einzeiler sein. Alles andere gehört in eine Cpp-Datei. Bei Templates sieht das anders aus. Da muß alles tatsächlich im Header stehen. Aber das ist ein anderes Thema.

    Ein Aufruf ist wirklich nicht so teuer. Eine bessere Programmstruktur ist weitaus wichtiger.

    Tommi



  • durch inline kann man auch code sparen, für getter/setter ist dr aufrufoverhead oft größer als der eingentlich code. zudem ist es möglich, dass von einem rückgabewert z.b vektor, nur ein element benutzt wird und manche compiler können den unnötigen teil dann weglassen beim inlinen.
    nachteile sind, neben dem, wie schon erwähnt, größerem code, dass einige optimierungen wie z.b. sprungvorhersagen weniger optimal ablaufen, weil anstatt von immer den selben codestellen bei denen der prozessor wüste wie das resultat beim letzten durchlauf war, immer identische, aber unbekannte codestellen vorkommen bei denen die cpu im schlimsten fall dauernd falsch iegt.

    inline ist nur ein hint, compiler dürfen meines wissens nach auch ohne den hint inlinen, können das inlinen aber auch ganz sein lassen trotz hint. beim intel und microsoftcompiler kann man das mit __forceinline erzwingen. bei gcc kann man meines wissens nach nen schwellenwert dafür übergeben bis wieviel instructions noch geinlined wird.

    große funktionen inlinned man manchmal, weil sie nur an einer stelle im code benutzt werden und eigentlich direkt an diese stelle hätte implementiert werden können, aber wir mögen ja keine one-funktion-sorces und deswegen gibt es ne saubere gliederung+inlining.



  • tntnet schrieb:

    Theoretisch könnte ich tatsächlich ein Programm schreiben, welches nur aus Headern besteht. Ich könnte auch auf so viele andere Sprachfeatures wie Schleifen (kann man durch goto ersetzen) oder Klassen (struct oder einfach mehrere Variable gehen auch). Da geht aber sehr viel verloren. Die Programme werden unleserlich und unwartbar.

    das klingt, als würden funktionen im header die programme unwartbar machen. das ist nicht der fall.

    Inline-Funktionen und -Methoden sollten in der Regel Einzeiler sein. Alles andere gehört in eine Cpp-Datei.

    auch das ist nicht der fall. in sachen aufgeräumtheit und so gehört alles in den header in die klasse rein. so wie bei java. das mit dem auslagern in die cpp ist eine folge unseres übersetzungsmodells, keine forderung aus übersichtlichkeitsgrüden.

    Ein Aufruf ist wirklich nicht so teuer. Eine bessere Programmstruktur ist weitaus wichtiger.

    das, was ich unter programmstruktur verstehe, ist völlig unabhängig davon, wo die funktionen stehen.



  • rapso schrieb:

    inline ist nur ein hint, compiler dürfen meines wissens nach auch ohne den hint inlinen, können das inlinen aber auch ganz sein lassen trotz hint. beim intel und microsoftcompiler kann man das mit __forceinline erzwingen.

    Selbst __forceinline bedeutet nicht sicher, daß die Funktion wirklich inline gesetzt wird (rekursive Funktionen, abgeschaltete Code-Optimierung, variable Argumentliste,...).



  • ja natürlich, wenn es nicht möglich ist zu inlinen, man den compiler dazu anweist es nicht zu tun oder den compiliervorgang nicht startet... 🤡 ...wird nicht geinlined, vermutlich.



  • Man sollte bei inline auch nie die physische Kopplung vergessen. In C++ ist jede inline-Funktion eine Funktion deren *Definition* überall dort sichtbar ist, wo die Funktion gerufen wird. D.h. aber natürlich, dass bei Änderung der Definition der Inline-Funktion alle Stellen die die Funktion verwenden neu übersetzt werden müssen. Das ist immer mindestens lästig.

    Imo ist die beste Regel zum Thema inline nach wie vor: Default ist nicht inline. Erst nach dem ein Profiler einen Performance-Vorteil durch inlinen bestätigt hat, ausgewählte Funktionen inline machen.

    In der FAQ: http://www.c-plusplus.net/forum/viewtopic-var-t-is-105893.html



  • HumeSikkins schrieb:

    Erst nach dem ein Profiler einen Performance-Vorteil durch inlinen bestätigt hat, ausgewählte Funktionen inline machen.

    👍

    das lässt sich auch gut realisieren indem man sich defines für verschiedene inlines macht

    z.b.

    #define MYINLINE inline
    //#define MYINLINE __forceinline
    //#define MYINLINE
    
    #define INLINE_ACCESSOR MYINLINE
    //#define INLINE_ACCESSOR
    #define INLINE_MATHLIB MYINLINE
    //#define INLINE_MATHLIB
    
    INLINE_ACCESSOR bool empty()const;
    


  • Imo ist die beste Regel zum Thema inline nach wie vor: Default ist nicht inline.

    Auch bei Einzeilern? 😮 😮 😮 😮



  • rapso schrieb:

    #define MYINLINE inline
    //#define MYINLINE __forceinline
    //#define MYINLINE
    
    #define INLINE_ACCESSOR MYINLINE
    //#define INLINE_ACCESSOR
    #define INLINE_MATHLIB MYINLINE
    //#define INLINE_MATHLIB
    
    INLINE_ACCESSOR bool empty()const;
    

    So einfach dürfte es nicht sein. Wenn ich inline verwenden will muss die Funktion ja im Header implementiert sein ( sonst kann sie ja nicht inline gemacht werden wenn der Compiler sie nicht sieht ) , wenn ich jetzt aber MYINLINE leer definiere dann gibts Linker-fehler wenn ich den Header mehrfach verwende.
    Oder verstehe ich da etwas falsch ?
    Kurt



  • ZuK schrieb:

    rapso schrieb:

    #define MYINLINE inline
    //#define MYINLINE __forceinline
    //#define MYINLINE
    
    #define INLINE_ACCESSOR MYINLINE
    //#define INLINE_ACCESSOR
    #define INLINE_MATHLIB MYINLINE
    //#define INLINE_MATHLIB
    
    INLINE_ACCESSOR bool empty()const;
    

    So einfach dürfte es nicht sein. Wenn ich inline verwenden will muss die Funktion ja im Header implementiert sein ( sonst kann sie ja nicht inline gemacht werden wenn der Compiler sie nicht sieht ) , wenn ich jetzt aber MYINLINE leer definiere dann gibts Linker-fehler wenn ich den Header mehrfach verwende.
    Oder verstehe ich da etwas falsch ?
    Kurt

    es stimmt schon, dass der compiler die funktionen sehen können muss. es ist aber nicht so sauber wenn man im header definitionen hatm da sollten nur deklarationen rein. es ist gängige praxis dafür .inl files zu nutzen. bei mir in etwa so

    //im header
    #ifndef _D_USE_NOT_INLINE_
    #include "DMutex.inl"
    #endif
    

    in der cpp

    #include "DMutex.hpp"
    #ifdef _D_USE_NOT_INLINE_
    #include "DMutex.inl"
    #endif
    

    statt dem auskommentieren für die defines bietet sich ein #ifdef _D_USE_NOT_INLINE_ an. 🙂



  • Ok das ist was ich mit "nicht so einfach" gemeint hatte. Deine Lösung finde ich ganz elegant. 🙂
    Kurt



  • Ich hätte mal eine Frage dazu: Müssen Inlinefunktionen immer im Header definiert sein? Geht es nicht auch so:

    //In der H-Datei:
    class kl
    {
        inline void fkt();
    };
    
    //In der CPP-Datei:
    void kl::fkt()
    {
        //...
    }
    


  • Dann schrieb:

    Ich hätte mal eine Frage dazu: Müssen Inlinefunktionen immer im Header definiert sein? Geht es nicht auch so:

    //In der H-Datei:
    class kl
    {
        inline void fkt();
    };
    
    //In der CPP-Datei:
    void kl::fkt()
    {
        //...
    }
    

    so wüste der compiler beim compilieren einer anderen cpp die diesen header includet nicht wie die implementiierung der funktion ist.



  • Dann schrieb:

    Ich hätte mal eine Frage dazu: Müssen Inlinefunktionen immer im Header definiert sein? Geht es nicht auch so:

    //In der H-Datei:
    class kl
    {
        inline void fkt();
    };
    
    //In der CPP-Datei:
    void kl::fkt()
    {
        //...
    }
    

    Nein. Zumindest nicht wenn du fkt auch in anderen Übersetzungseinheiten (außer in der in der fkt definiert ist) aufrufen möchtest. D.h. sinnvoll ist die von dir gezeigte Anwendung überhaupt nur dann, wenn die inline Funktion private ist und die Klasse keine Long-Distance-Freundschaften pflegt.



  • Geht wenigstens das hier?

    //Alles in der H-Datei: 
    class kl 
    { 
        inline void fkt(); 
    }; 
    
    void kl::fkt() 
    { 
        //... 
    }
    

    Ich fände es nämlich ziemlich unordentlich, würde man es so schreiben:

    //Alles in der H-Datei: 
    class kl 
    { 
        inline void fkt()
        {
            //...
        }
    };
    

    Vor allem, wenn man da noch mehr solcher Methoden hat.



  • Ja, das geht. Aber nochmal inline vor die Definition.



  • Dann schrieb:

    Geht wenigstens das hier?

    //Alles in der H-Datei: 
    class kl 
    { 
        inline void fkt(); 
    }; 
    
    void kl::fkt() 
    { 
        //... 
    }
    

    Ich fände es nämlich ziemlich unordentlich, würde man es so schreiben:

    //Alles in der H-Datei: 
    class kl 
    { 
        inline void fkt()
        {
            //...
        }
    };
    

    Vor allem, wenn man da noch mehr solcher Methoden hat.

    ich finde beides unordentlich. da sehen dann die header aus wie mit einer implemenationsdatei gekreuzt.

    lieber seperate datei anlegen 😉



  • volkard schrieb:

    tntnet schrieb:

    Theoretisch könnte ich tatsächlich ein Programm schreiben, welches nur aus Headern besteht. Ich könnte auch auf so viele andere Sprachfeatures wie Schleifen (kann man durch goto ersetzen) oder Klassen (struct oder einfach mehrere Variable gehen auch). Da geht aber sehr viel verloren. Die Programme werden unleserlich und unwartbar.

    das klingt, als würden funktionen im header die programme unwartbar machen. das ist nicht der fall.

    Inline-Funktionen und -Methoden sollten in der Regel Einzeiler sein. Alles andere gehört in eine Cpp-Datei.

    auch das ist nicht der fall. in sachen aufgeräumtheit und so gehört alles in den header in die klasse rein. so wie bei java. das mit dem auslagern in die cpp ist eine folge unseres übersetzungsmodells, keine forderung aus übersichtlichkeitsgrüden.

    Ein Aufruf ist wirklich nicht so teuer. Eine bessere Programmstruktur ist weitaus wichtiger.

    das, was ich unter programmstruktur verstehe, ist völlig unabhängig davon, wo die funktionen stehen.

    @volkard
    Da bin ich anderer Meinung! Die Trennung von Deklaration und Definition (einer Funktion) ist übersichtlicher. Das gilt zumindest dann, wenn ich eine Klasse nur verwenden möchte, also eigentlich nur die (public) Schnittstelle benötige. Das ist sehr aufwändig, wenn eine nichttriviale Klasse komplett inline ist. Sieh dir eine beliebige STL-Implementierung an, dann weißt du, was ich meine. Ich finde, Java ist in dieser Hinsicht kein Vorbild. Da funktioniert das nur einigermaßen, da es standardmäßig JavaDoc gibt...

    Stefan.


Anmelden zum Antworten