parameter als refernez oder wert?



  • ichfalk schrieb:

    mit Werten:
    deklaration: funktion(int &i)
    aufruf: funktion(i)

    Huh?`Das ist doch auch by Reference.

    Normales by value geht so:

    funktion(int i)

    Das sollte bei einem int das schnellste sein.
    Du mußt abwägen... je nachdem wie teuer die Kopie ist ist das eine oder andere Verfahren günstiger. Außerdem wenn Du den Wert verändern willst, dann mußt Du sowieso by reference.

    Und dann haste die zwei von Dir genannten Möglichkeiten.



  • vielleicht war meine int-variable nicht geschickt gewählt...
    wenn mal also ein beliebig kompliziertes struct dafür nimmt, was passiert bei den aufrufen?

    falls ich mit "&bel_struct" aufrufe, übergebe ich der funktion ja nur die adresse, oder?
    und bei dem aufruf mit "bel_struct"? in der deklaration der funktion steht ja "&bel_struct", wird deswegen auch nur die adresse übergeben?
    (ohne das referenz-& in der deklaration würde ja sozusagen "bel_struct_copy" angelegt, also ziemlich viel mehr Platz, den ich dann auch noch zurückgeben müsste...)

    Falk.



  • wie gesagt, ohne das & wird eine kopie angelegt!
    Egal ob von strukt oder int oder sonstwas!

    mit & wird das objekt selbst "aufgerufen" (über seine adresse)



  • die übergabe als referenz hat genau den selben effekt wie die übergabe des zeigers, egal ob der zeiger/die referenz auf ein int oder ein struct oder sonstwas verweist.

    nur daß du bei übergabe per referenz halt nicht immer ein * davor setzen mußt, um den wert zu ändern. ist halt bequemer.



  • Nunja, ich weis nicht was der Compiler daraus macht, aber wenn man einen Pointer übergibt wird ja eine lokale Variable in der Funktion angelegt. Bei einer Referenz musst du aufpassen wenn du Literals übergibst:

    #include <iostream>
    
    using namespace std;
    
    void ausgabe(int& wert)
    {
        cout << "Wert: " << wert << endl;
    }
    
    void ausgabe_const(int const& wert)
    {
        cout << "Wert: " << wert << endl;
    }
    
    int main()
    {
        ausgabe(5);          // PENG! 5 ist konstant
    	                     // azsgabe() könnte versuchen 5 zu ändern.
    
        ausgabe_const(10);   // Funktioniert
    
        return 0;
    }
    


  • ist ja interessant aus welcher Gegend kommt denn ichFalk ????



  • ... denn dafür sind sie da



  • nur damit ich weiss, dass ich euch alle richtig verstanden habe:

    funktion(bel_struct &aender_das)
    ist gut

    funktion(bel_struct *aender_das)
    ist gleich gut
    (aber ist es bei 'ner Masse von Aufrufen gleich schnell?)

    funktion(bel_struct aender_das)
    erzeugt eine Kopie, die ich (geändert) mit return zurückgeben muss
    also nicht gut

    @auchFalk: Düsseldorf->Aachen.



  • Referenzen sind im Grunde "Zeiger für Arme". Das fehlen von Klimaanlage, die Möglichkeit Adressen nicht erneut zuweisen zu können etc. machen sie für einige Sachen zwar ungeeignet, dafür ist das Auftreten von Programmierfehlern (wie in C) deutlich reduziert.



  • ichfalk schrieb:

    nur damit ich weiss, dass ich euch alle richtig verstanden habe:

    funktion(bel_struct &aender_das)
    ist gut

    funktion(bel_struct *aender_das)
    ist gleich gut
    (aber ist es bei 'ner Masse von Aufrufen gleich schnell?)

    funktion(bel_struct aender_das)
    erzeugt eine Kopie, die ich (geändert) mit return zurückgeben muss
    also nicht gut

    @auchFalk: Düsseldorf->Aachen.

    *funktion(bel_struct aender_das) wird vom compiler in genau den selben code übersetzt wie funktion(bel_struct &aender_das), nur daß man beim zugriff auf aender_das eben kein * davor setzten muß. der unterschied ist rein syntaktisch. dh es ist auch genauso schnell. referenzen sind halt bequemer und sehen besser aus



  • FireFlow schrieb:

    Nunja, ich weis nicht was der Compiler daraus macht, aber wenn man einen Pointer übergibt wird ja eine lokale Variable in der Funktion angelegt.

    Käse.

    FireFlow schrieb:

    ausgabe(5);          // PENG! 5 ist konstant
                             // azsgabe() könnte versuchen 5 zu ändern.
    

    Wobei hier nicht die Anwendung PENG macht, sondern der Compiler hat was zu meckern. Da Literale nunmal konstant sind, kann man sie auch nicht non-const referenzieren. Also kein Grund zur Sorge.

    ichfalk schrieb:

    funktion(bel_struct &aender_das)
    ist gut

    Weder noch, es ist einfach ein Referenzparameter. Da man dich bisher ziemlich verwirrt hat (imo 🙂 ), nochmal eine hoffentlich verständliche Kurzbeschreibung:

    void funktion(int a) // trivialer Typ und Aenderung nicht erforderlich - deshalb Uebergabe by-value
    void funktion(const int a) // trivialer Typ und Aenderung nicht erforderlich - const macht keinen Sinn, weil Uebergabe sowieso by-value
    void funktion(int& a) // trivialer Typ und Aenderung erforderlich - deshalb Uebergabe by-reference
    void funktion(const int& a) // trivialer Typ und Aenderung nicht erforderlich - macht wenig Sinn, weil wir ja triviale Werte by-value uebergeben
    void funktion(foo a) // nicht-trivialer Typ und Aenderung nicht erforderlich - macht wenig Sinn, da Kopie zu teuer ist
    void funktion(const foo a) // nicht-trivialer Typ und Aenderung nicht erforderlich - const macht keinen Sinn, weil Uebergabe sowieso by-value
    void funktion(foo& a) // nicht-trivialer Typ und Aenderung erforderlich - deshalb Uebergabe by-reference
    void funktion(const foo& a) // nicht-trivialer Typ und Aenderung nicht erforderlich - deshalb Uebergabe als konstante Referenz
    

    Alles was Referenzen betrifft, kann man genauso mit Zeigern machen, nur ist das eher C Style. Da normalerweise Compiler Referenzen auch nur über Zeiger realisieren, sollte idR sogar identischer Maschinencode entstehen. Die Unterschiede sind dann lediglich semantischer Natur. Zudem sollte man bedenken, dass ein Zeiger nicht unbedingt auf ein gültiges Objekt verweisen muss.



  • ichfalk schrieb:

    angelegt, also ziemlich viel mehr Platz, den ich dann auch noch zurückgeben müsste...)

    Viel mehr ist relativ: Wenn die struct nur ein paar ints enthält ist by value vermutlich trotzdem schneller.
    Den Speicher mußt Du auch nicht zurückgeben. Das ganze passiert auf dem Stack und da kostet Speicher allokieren nicht so viel.


Anmelden zum Antworten