inline oder nicht inline, das ist hier die Frage...



  • Hi,

    ich bin gerade am überlegen ob inline noch Sinnvoll ist für kleinere Funktionen.

    Grund ist folgender: Der Compiler wird immer besser (Benutze momentan VC++2005Express) und merkt sicherlich wann und wo er was optimieren kann und wo es sinnvoll ist. (Wie z. B. bei dem Schlüsselwort register)

    Ich habe haufenweise mathematische Funktionen in meinem Programm für 3D Berechnungen. Diese Funktionen sehen alle fast so aus (im Umfang)

    inline vector operator *= (const vector& v)	
    {
        x *= v.x; 
        y *= v.y; 
        z *= v.z; 
    
        return *this;
    }
    
    // bzw.
    
    inline float vectorLength (const vector& v)
    {
        return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
    }
    

    Hier stellt sich mir die Frage, ob es überhaupt noch sinnvoll ist hier inline zu benutzen und die Funktionen im Header zu definieren, anstatt ohne inline dafür aber in der cpp-Datei.

    Ich bin der Meinung, das Express (oder andere aktuelle Compiler) dies sowieso direkt inline machen, da sie erkennen, das diese Funktionen oft aufgerufen werden und sehr klein sind. (Release Mode versteht sich!)

    Wie denkt ihr darüber? inline für diese Dinger noch sinnvoll oder genau wie bei register auf den Compiler vertrauen? 🙄



  • ################## schrieb:

    Ich bin der Meinung, das Express (oder andere aktuelle Compiler) dies sowieso direkt inline machen, da sie erkennen, das diese Funktionen oft aufgerufen werden und sehr klein sind. (Release Mode versteht sich!)

    Das glaube ich nicht, da er beim compilieren der Übersetzungseinheit B (die die Funktionen benutzt) keinen Zugriff auf den Objektcode der Übersetzungseinheit A (wo die Funktionen definiert sind) hat. Und ich glaube nicht dass der Linker compilierten Code ersetzt.

    Also geht inlining nur, wenn die Definition in der selben ÜE sichtbar ist. Und dann ist das Keyword "inline" eh nur noch ein Hint, der Compiler kann sich jederzeit dagegen entscheiden.



  • Moderne Compiler koennen ueber mehrere Uebersetzeungseinheiten inweg optimieren und inlinen, bei Microsoft heisst dieses feature "Whole Program Optimization".



  • Shade Of Mine schrieb:

    Moderne Compiler koennen ueber mehrere Uebersetzeungseinheiten inweg optimieren und inlinen, bei Microsoft heisst dieses feature "Whole Program Optimization".

    Ergo: Für meine Funktionen daoben absolut unnütz, da der Compiler das sowieso schon macht? 😕



  • @Shade Of Mine
    einfaches ja oder nein würd mir reichen 🙂



  • Man sollte vllt. noch den Befehl

    #pragma auto_inline(on)
    

    bzw.

    #pragma auto_inline(off)
    

    erwähnen, mit denen man ganze Definition-Blöcke 'inlinen' kann 😉

    PS: Geht nur beim MS Compiler!



  • @CodeFinder
    DAS IST MAL GEIL!!!! DANKE!!!

    achja noch ne frage am Rande: was ist besser?

    Variante 1

    const vector& vector::operator *= (const vector& other)
    {
        x *= other.x; // X-Achse
        y *= other.y; // Y-Achse
        z *= other.z; // Z-Achse
    
        return (*this);
    }
    
    const vector& vector::operator *= (float value)
    {
        return ((*this) *= vector (value, value, value));
    }
    

    oder Variante 2:

    const vector& vector::operator *= (const vector& other)
    {
        x *= other.x; // X-Achse
        y *= other.y; // Y-Achse
        z *= other.z; // Z-Achse
    
        return (*this);
    }
    
    const vector& vector::operator *= (float value)
    {
        x *= value; // X-Achse
        y *= value; // Y-Achse
        z *= value; // Z-Achse
    
        return (*this);
    }
    

    Bitte mit Begründung wenn es geht 🙂

    Persönlich finde ich variante 1 besser, da man diese leichter pflegen kann (sonst muss man an 2 stellen gleichzeitig!) und mehr code erspart. jedoch was ist mit dem konstruktor der zusätzlich aufgerufen wird?! 😮



  • Bei Variante 1 muss erst noch das neue Objekt gefüllt werden.
    Wenn du so sehr optimieren möchtest, solltest du dich eventuell noch über SSE 1/2/3 informieren.

    Ich gebe bei +=, *= etc. im übrigen keine Referenz auf ein konstantes Objekt zurück, ich weiß aber auch nicht, wie es standardmäßig ist.



  • @Neku
    nee es geht mir nur um den Codetechnischen aufbau, was zu bevorzugen wäre (und was natürlich schnell ist ;))

    ISSE bringt mir nichts, wenn der Aufbau des Codes Müll ist 🙂 Right?

    Wegen der Referenz: Ich habe oft gesehen, das dort einige keinen Rückgabewert habe und andere nur eine Kopie seiner selbst und wiederum andere eine Referenz 🙂

    Würd mich auch mal interessieren, was hier zu bevorzugen ist.


  • Mod

    ############### schrieb:

    Persönlich finde ich variante 1 besser, da man diese leichter pflegen kann (sonst muss man an 2 stellen gleichzeitig!) und mehr code erspart. jedoch was ist mit dem konstruktor der zusätzlich aufgerufen wird?! 😮

    theoretisch ist alles wegoptimierbar. und praktisch wissen wir nicht, ob das geschehen wird.
    andererseits verstehe ich nicht, was für eine art vektor hier implementiert wird. dein *= operator berechnet weder ein sklar- noch vektor-produkt. ich habe also gweisse zweifel, dass zwischen beiden operatoren ein logischer zusammenhang besteht (jedenfalls dann, wenn der übliche vektorbegriff und die üblichen operationen darauf implementiert werden sollen).



  • @camper
    Ich weiß, mathematisch nicht korrekt, aber Scalar und Punktprodukt berechne ich über seperate Funktionen.


  • Mod

    Neku schrieb:

    Ich gebe bei +=, *= etc. im übrigen keine Referenz auf ein konstantes Objekt zurück, ich weiß aber auch nicht, wie es standardmäßig ist.

    es gibt keinen standard für die x= operatoren, denn diese werden nicht implizit definiert. allerdings ist das ergebnis für die eingebauten operatoren immer ein non-const lvalue. für operator= ist die frage dagegen klar: auch der implizit definierte operator gibt eine referenz auf nicht-const zurück.



  • @camper
    bitte was? *nichts versteh* : confused :


  • Mod

    ########### schrieb:

    @camper
    Ich weiß, mathematisch nicht korrekt, aber Scalar und Punktprodukt berechne ich über seperate Funktionen.

    es gibt nat. für alles grenzfälle. ich halte variante 2 hier für besser, denn die einzelne zeile in der ersten variante ist um ein vielfaches komplexer - ohne das das einen fundamentalen zugewinn bringt. es steht ja zu erwarten, dass beide funktionen direkt nacheinander implementiert werden - somit ist der zugewinn an wartbarkeit in diesem falle eher theoretischer natur. das könnte anders aussehen, wenn du erheblich mehr solcher funktionen hast, die auf diesen operator zurückzuführen sind.


  • Mod

    schrieb:

    @camper
    bitte was? *nichts versteh* : confused :

    fazit: gibt normale referenzen auf *this zurück.



  • @camper
    also kein const? hmn okay. weiß zwar net warum aber egal 🙂



  • ########## schrieb:

    @camper
    also kein const? hmn okay. weiß zwar net warum aber egal 🙂

    vector v1(1,2,3), v2(4,5,6);
    v1 += 1 += v2 += 1;
    

    😮


  • Mod

    vector v1(1,2,3), v2(4,5,6);
    v1 += 1 += v2 += 1;
    

    😮

    das würde auch mit referenzen auf const oder kopien als rückgabewert funktionieren, denn alle diese operatoren sind rechtsassoziativ. hier müsste der operator allerdings als freie funktion implementiert werden, da die erste 1 als linker operand auftritt.



  • camper schrieb:

    vector v1(1,2,3), v2(4,5,6);
    v1 += 1 += v2 += 1;
    

    😮

    das würde auch mit referenzen auf const oder kopien als rückgabewert funktionieren, denn alle diese operatoren sind rechtsassoziativ. hier müsste der operator allerdings als freie funktion implementiert werden, da die erste 1 als linker operand auftritt.

    My fault.

    vector v1(1,2,3), v2(4,5,6); 
    (v1 += 1) += v2 += 1;
    

Anmelden zum Antworten