Funktionsparameter: Referenz - Ja / Nein ?



  • Hallo zusammen 🙂

    Wenn ich Operatoren für meine eigene Klasse überlade, macht es dann Sinn Referenzparameter zu benutzen?

    Bsp:

    // x, y, z = Variablen in meiner VectorKlasse
    
    inline VECTOR3 operator+ (VECTOR3 vVec) { 
    
       return VECTOR3(x+vVec.x, y+vVec.y, z+vVec+z);
    
    }
    

    Als Parameter wird so nur eine Kopie übergeben oder? Das heißt ja, dass jedes mal wenn diese arithmetische Funktion durchgeführt wird, wird eine temporäre Variable erzeugt (VECTOR3 vVec). Sollte ich also lieber die Referenz benutzen um so Speicher und Rechenzeit zu sparen?

    Bin noch Anfänger und weiß nicht so genau, ob ich das oben richtig erklärt habe 🙂

    Danke schonmal. Grüße Jan.



  • Du lieferst zwar kein gutes Beispiel, weil so ziemlich jeder Compiler die gesamte Funktion inlinen wird (was nichts damit zu tun hat, dass du da inline vorgeschrieben hast, das ist nur nötig, damit es überhaupt kompiliert, weil ich davon ausgehe, dass das so in einem Header steht), es somit also gar keinen Funktionsaufruf gibt, wobei Du ja von inlinen offenbar ausgehst, da frage ich mich, warum Du gerade zu diesem Beispiel die Frage hast.

    Aber allgemein gesprochen, könnte man für simple typen ein Template bereithalten, dass über sizeof entscheidet, oder der Parameter-Typ by-value oder by-const-ref ist, und das dann nach dem Profilieren mit den größen anpassen.

    Ansonsten meine Faustregel: 1-2 eingebaute Typen kopieren? By-Value. Sonst? By-Const-Ref. Aber im Moment bin ich echt faul und übergebe auch std::wstring und alles andere By-Value, wenn's nicht kritisch ist, hehe.



  • Bzgl Parameterübergabe bietet sich hier die Übergabe als Referenz-auf-const an:

    struct vector3 {
      double x,y,z;
      :::
      vector3 operator+(vector3 const& rechteseite) const {
        return vector3(.....);
      }
      :::
    };
    

    Das const am Ende ist auch wichtig. Man will aber eigentlich solche Operatoren eher als freie Funktion implementieren. Gerade, wenn du implizite Umwandlungen unterstützt, macht das viel Sinn. Du findest hier auf dieser Seite einen Artikel zum Thema Operator-Überladung, der meines Wissens auch darauf eingeht. Was ich hier auch nicht so schön finde, ist, dass man hier auf die Elemente nicht mit einem Index zugreifen kann. Noch etwas: Wenn Du die Funktion innerhalb der Klasse definierst, ist sie schon automatisch eine inline-Funktion. Deswegen kannst du dir da das inline-Schlüsselwort sparen.

    Ich empfehle dir aber auch, mal Eigen::Vector3d zu testen.



  • krümelkacker schrieb:

    Was ich hier auch nicht so schön finde, ist, dass man hier auf die Elemente nicht mit einem Index zugreifen kann.

    Immer wieder hat man da irgendwie das Problem, dass man Packed-Array, XYZ und Array im C++ irgendwie nicht unter einen Hut bekommt, obwohl es doch eigentlich nur um ein mehr oder minder großes Feld von gleichen Typen geht. Ich finde das eine Schwäche von C++, aber muss man halt für sich selber beurteilen.



  • Achso. Also sind Klassenmethoden bzw. Elementfunktionen immer automatisch als inline Deklariert? inline-Funktionen ertsellen ja keinen neuen Stack, sondern funktionieren wie Makros, die den Funktionsinhalt einfach nur an die Stelle der Funktion schreiben, sodass auch das Referenzieren nicht nötig ist?

    Habe ich das so richtig verstanden?

    Das mit der Typumwandlung und const habe ich noch nicht verstanden, aber das werde ich mir nochmal genauer angucken.

    Vielen Dank für die schnelle Antwort 🙂



  • Ein guter Compiler inlined jede kleine Funktion, unabhängig davon wo sie steht.



  • Obstsalat schrieb:

    Achso. Also sind Klassenmethoden bzw. Elementfunktionen immer automatisch als inline Deklariert?

    Nein eigentlich nicht, das macht man nur bei kleinen Funktionen, wo durch den Aufruf der Funktion mehr Rechenzeit verschwendet wird als es nötig wäre wenn dort keine Funktion wäre...
    Daher du kannst dir das so vor stellen:
    Wenn du eine Funktion:

    inline int Addiere(int a,int b){
    return a+b;
    }
    

    hast und die main:

    int main(){
    int c = 10;
    int d = 20;
    int e = Addiere(c,d);
    }
    

    Dann wird es sich nicht lohnen die Funktion Aufzurufen, das kannst du dir so vorstellen, dass der PC erst mal die Funktion suchen müsste, daher das dauert länger als wenn dort einfach nur e=c+d; stehen würde.
    Natürlich bei langen Funktionen, lohnt sich ein Inline nicht...
    MfG



  • Vergiss inline erst einmal. Geringere Compilezeit-Abhängigkeiten sind wichtiger, schreib daher die Implementierung der Methoden in die .cpp-Datei. Üblicherweise weiss der Compiler sowieso besser als du, wann er Funktionen inline nimmt.

    Das Schlüsselwort inline sollte hauptsächlich aus Linkage-Gründen verwendet werden, nämlich wenn man eine Funktion im Header definieren muss (z.B. Header-Only-Bibliothek).

    derFer schrieb:

    das kannst du dir so vorstellen, dass der PC erst mal die Funktion suchen müsste

    Ne, kannst du nicht. Da wird nichts gesucht, die Adresse der Funktion ist zur Laufzeit längst bekannt. Wie gesagt: inline vorerst vergessen. Es ist unwahrscheinlich, dass dadurch nennenswerte Optimierungen zustande kommen. Durch inkompetente Anwendung des Schlüsselworts kannst du sogar das Gegenteil erreichen. Daher schön den Compiler und Linker walten lassen...



  • Naja vielleicht sucht der nichts, aber es braucht trotzdem Rechenzeit, also ein Funktionsaufruf (durch das legen der Rücksprungaddresse und der Parameter auf den Stack)...
    Naja für den Anfang hast du aber Recht braucht man inline eigentlich nicht.
    (Auch wenn ein guter Compiler merkt wann es sich lohnt und wann nicht)...
    MfG



  • Obstsalat schrieb:

    Achso. Also sind Klassenmethoden bzw. Elementfunktionen immer automatisch als inline Deklariert?

    Nein. Nur dann, wenn du die Funktionen innerhalb der Klassendefinition definierst. Wenn Du sie nur deklarierst und außerhalb definierst, dann sind sie nicht automatisch inline.

    Obstsalat schrieb:

    inline-Funktionen ertsellen ja keinen neuen Stack, sondern funktionieren wie Makros, die den Funktionsinhalt einfach nur an die Stelle der Funktion schreiben, sodass auch das Referenzieren nicht nötig ist?

    Habe ich das so richtig verstanden?

    Nein, nein, nein. Wie der Compiler Funktionen bzw Funktionsaufrufe übersetzt, ist ganz allein sein Bier. Der Status einer Funktion, inline oder nicht inline, hat mit dem tatsächlichen "Inlining", was du im Kopf hast, weniger zu tun. All die Optimierungen, die der Compiler durchführt oder sein lässt, ändert nichts an der Semantik deines Programms. Ob eine Funktion inline ist oder nicht, sollte dir aber klar sein, weil sich die One-Definition-Rule auf diese Eigenschaft bezieht und für Inline-Funktionen Ausnahmen macht. Das schlaue C++ Buch, was dir vorliegen sollte, sollte dir irgendwo diese One-Definition-Rule erklären. Das ist wichtig.


Log in to reply