Funktionen call by value und call by reference/ unterschied, vorteile, nachteile



  • Hallo,

    ich arbeite seit kurzem mit funktionen.

    kann mir jemand von euch bitte auf verständlich weise erklären welche vorteil bzw. nachteile eine call by valuce funktion gegenüber einer call by refernce funktion hat?

    das einzige was ist weiß ist, dass bei der zweiteren nicht mit kopieen der werte gearbeitet wird sondern mit speicherstellen. aber was genau heißt das?

    kenne leider nur einige leichte beispielaufgaben beider funktionstypen aber ich bin der meinung das es keine rolle spielt mit welcher funktion man arbeite.
    höchstwahrscheinlich sit die aussage falsch aber warum??

    DANKE!



  • schlicht und einfach bedeuted das, dass du wenn du bei call-by-ref den Parameter in der Funktion veränderst, sich auch die Variable die beim Aufruf übergeben wurde verändert => eine Referenz, ein Alias sozusagen

    Call-by-value kopiert eben, wodurch du die Variablen auch problemlos verändern kannst u.s.w. Die normale Übergabe halt
    Call-by-reference kannst du a) für Ausgabeparameter verwenden, wenn deine Funktion mehr als nur 2 Werte zurück geben soll und du keine Struktur o.ä. verwenden willst
    b) kopieren großer Objekte kostet Zeit



  • DANKE!

    blöde frage aber was genau verstehst du unter einen parameter!?



  • parameter sind die daten, die an die funktion übergeben werden:
    void function(int parameter1, char parameter2);

    wenn du jetzt eine große klasse (eine, die viel speicher verbraucht bzw. viele attribute hat) by value übergibst, wird die klasse bit für bit kopiert. Wenn du sie aber by reference übergibst, wird der funktion gesagt, _an welcher Stelle_ im arbeitsspeicher das bereits existierende objekt ist. Dadurch spart man die ganze Kopiererei und bei großen Objekten geht es schneller.
    Da beim call by value nur eine Kopie des Objektes übergeben wird, bringt es wenig, wenn die Funktion sachen an dem Objekt ändert, da sie lediglich auf _eine Kopie_ des Objektes zugreift. Wenn du also eine funktion schreibst, die objekte verändern soll, solltest du call-by-reference (oder übergabe über pointer, aber das bringt häufig keine weiteren vorteile und macht es nur komplizierter) verwenden.



  • DANKE!

    @Heinzelotto
    Da beim call by value nur eine Kopie des Objektes übergeben wird, bringt es wenig, wenn die Funktion sachen an dem Objekt ändert, da sie lediglich auf _eine Kopie_ des Objektes zugreift. Wenn du also eine funktion schreibst, die objekte verändern soll, solltest du call-by-reference (oder übergabe über pointer, aber das bringt häufig keine weiteren vorteile und macht es nur komplizierter) verwenden.

    Kannst du mir, dass bitte an einen Beispiel erklären?

    Gehen wir mal davon aus ich habe eine Funktion die eine Zahl rundet.

    -Im ersten Schritt wird die zu rundene Zahl in die Funktion geladen.

    -innerhalb der Funktion wird dann die Zahl gerundet

    -Am ende wird die gerundete Zahl zurückgegeben

    Wenn ich deine Aussage jetzt richtig verstanden habe, wird durch die Funktion ein verändertes objekt zurückgegeben nämlich die gerundete zahl.

    Aber Funktionen geben doch immer veränderte Objekte zurück.

    Wie ist dies ganz genau zu verstehen?!

    DANKE!



  • Funktionen geben eben nicht immer etwas zurück.

    Du kannst auch eine Funktion call-by-reference machen und nichts zurückgeben.

    Dann hast du sowas

    int main( void )
    {
        int a = 5,
            b = 0;
    
        a = 2;
    
        b = app(a);
        //b == 6 aber a == 5 weil nur die kopie von a verändert wurde
    
        setBlikeApp( &b, a );
        //b == 6 aber a == 5 weil eine kopie von a verändert wurde, aber über original b geschrieben wurde
    }
    
    int app( int a )
    {
        a++;//5+1
        return a;//6 zurückgeben
    }
    
    void setBlikeApp( int *b, int a )
    {
        b = a++;//oder evtl &b = a++;
    }
    

    habe den Code nicht getestet kann also sein das ich noch einen fehler gemacht habe... int* sind immer blöde...



  • aber was bringt mir eine funktion die nichts macht bzw nicht zurück gibt.

    ich stelle mir, dass derzeit so vor.

    - man kann call by value funktionen nutzen um einen wert zurückzugeben
    die rückgabe mehrere werte ist nicht möglich. KLAR!

    - bei der rückgabe von werten bzw objekten sollten aber trotzdem immer call by
    reference funktionen genutzt werden auch wenn es sich nur um einen wert
    handelt,oder?

    - aber warum gibt es denn call by value überhaupt? eventuell ist call by value
    dazu gedacht um text ausgaben zurückzugeben. textausgaben sind ja keine
    veränderten werte sondern nur eine art formatierung

    kann mir den quelltext nicht viel anfangen

    eventuell würde es mir helfen wenn ihr mir den unterschied anhand das follgenden codes erklären könntet:

    #include <iostream>
    
    using namespace std;
    
    void Dreieckstausch (int*zeiger1, int *zeiger2) //eine call by refernce funktion beginnt mit void und nicht mit int usw.
    {
         int ihilfsfeld;
         ihilfsfeld = *zeiger1;
         *zeiger1 = *zeiger2;
         *zeiger2 = ihilfsfeld;
         return;
    }     
    
    int main()
    {
    
    int izahl=4, izahl2=9;
    
    cout << "Inhalt der Variablen VOR Aufruf der Funktion: " << endl << izahl << endl << izahl2 << endl;
    
    Dreieckstausch (&izahl, &izahl2);
    
    cout << "Inhalt der Variablen NACH Aufruf der Funktion: " << endl << izahl << endl << izahl2 << endl;
    
    cout << endl << endl;
    system("PAUSE");
    return 0;    
    }
    

    DANKE!



  • Ui das is C++ da weiß ich nich wie mit Call-by-Ref und so gearbeitet wird.

    Aber folgendes:

    MAch mal eine Funktion die mehr als 1 Variable verändert mit Call-By-Value...(das ist unmöglich! Allein daher muss es auch call-by-referenze geben)

    Ahso und void-Funktionen haben keinen return.



  • Call-by-value heißt "Aufruf per Wert" und nicht "Rückgabe per Wert". Verabschiede Dich von der Rückgabe-by-value, es geht hierbei nur um die Parameter! Deshalb hat Call-by-value/-reference auch nichts damit zu tun, dass der Rückgabetyp void ist.



  • Hi,

    mal an einem anfassbaren Beispiel beschrieben.

    Wen Du ein paar Äpfel hast und Du fotografierst die oder machst Gipsabdrücke, die Du an die Funktion übergibst, dann ist das Call by Value. Dann kann die Funktion bewerten ob sie schön sind...

    Wenn aber die Äpfel geschält werden müssen, dann reicht weder ein Foto noch ein Abdruck, dann müssen die Äpfel selber rüber, Call by Referenz.

    Gruß Mümmel



  • muemmel schrieb:

    Hi,

    mal an einem anfassbaren Beispiel beschrieben.

    Wen Du ein paar Äpfel hast und Du fotografierst die oder machst Gipsabdrücke, die Du an die Funktion übergibst, dann ist das Call by Value. Dann kann die Funktion bewerten ob sie schön sind...

    Wenn aber die Äpfel geschält werden müssen, dann reicht weder ein Foto noch ein Abdruck, dann müssen die Äpfel selber rüber, Call by Referenz.

    Gruß Mümmel

    Naja, also ich weiss nicht so recht ob sowas überhaupt verglichen werden kann.
    Hilft den sowas? Kann mir nicht vorstellen, dass sowas hilft.
    Simon



  • template <typename T>
    T add(T a, T b)
    {
    return a+b;
    }
    

    Wäre eine Funktion, die 2 Werte eines beliebigen Datentyps addiert und die Summe zurückgibt.
    Wenn die Datentypen sehr viel Speicherplatz verbraucht wird hier allerdings 3 mal kopiert, 2 mal bei der Übergabe und einmal bei der Rückgabe. Da wir hier von Übergabe sprechen, ignorieren wir die Rückgabe einfach mal.

    template <typename T>
    T add(const T& a, const T& b)
    {
    return a+b;
    }
    

    Dieses Beispiel macht genau das selbe, nur dass bei der Übergabe nichts kopiert wird, sondern Referenzen benutzt werden, also die Funktion wird nur auf die Variablen verwiesen(normalerweise dürfte da kein Literal, sondern nur eine Variable übergeben werden, aber durch das const wird auch ein Literal akzeptiert). Da in diesem Beispiel a und b sowieso nicht verwendet wird, nimmt man also eine konstante Referenz, was schneller ist.

    Oder aber du willst nicht, dass die Summe zurückgegeben wird, sondern dass der zweite Parameter zum ersten addiert wird

    template <typename T>
    void add(T& a, const T& b)
    {
    a += b;
    }
    

    wenn man diese Funktion jetzt folgendermaßen benutzt

    int var(2);
    add(var, 3);
    //hier ist var 5
    


  • hallo,

    ich weiß ihr meint es mit euren vielen antworten alle ut aber leider reicht mein wissen nicht aus eure antworten zu verstehen.

    also machen wir das anders.

    kann mir jemand erklären warum folgendes programm nicht funktioniert?

    #include <iostream>
    
    using namespace std;
    
    void durchschnitt (int *zahl1, int *zahl2)
    {
         int durchschnitt;
         durchschnitt=(zahl1+zahl2)/2
    }
    
    int main()
    {
    
    int zahl1=5, zahl2=25, durchschnitt;
    
    durchschnitt=durchschnitt(&zahl1, &zahl2);
    
    cout << durchschnitt; 
    
    system("PAUSE");
    return 0;
    }
    

    kann man in call by ref funktionen nicht rechnen??



  • funktioniert nicht ist keine besonders aussagekräftige Fehlerbeschreibung. Bekommst Du eine Fehlermeldung vom Compiler? Dann zeig uns die bitte. Oder bekommst Du ein falsches Ergebnis, dann zeig uns bitte das Beispiel.

    Generell könnte es aber schonmal helfen, wenn Du nicht sowohl eine Funktion als auch eine Variable mit dem Namen durchschnitt hast.



  • 1. übergibst du nen Pointer und das ist nicht wirklich call-by-reference.
    2. rechnest du mit addressen, was unsinn ist, du musst die Parametern bei Pointern natürlich erst dereferenzieren => *zahl1 + *zahl2
    3. ist die Größe von int und die eines Pointers meistens identisch, wodurch das ganze mehr oder weniger nutzlos wird, außer du willst, dass ein Pointer NULL sein kann(was auch der Grund für eine Pointerübergabe wäre), was hier allerdings a) sinnlos wäre und b) auch noch abstürzen würde



  • @
    JustAnotherNoob

    was heißt ich übergebe einen "pointer"?!
    und warum ist das nicht call by reference?

    habe den code jetzt verbessert

    #include <iostream>
    
    using namespace std;
    
    void durchschnitt (int *zahl1, int *zahl2)
    {
         int durchschnitt;
         durchschnitt=(*zahl1+*zahl2)/2;
    }
    
    int main()
    {
    
    int zahl1=5, zahl2=25, ergebnis;
    
    ergebnis = durchschnitt(&zahl1, &zahl2);
    
    cout << ergebnis; 
    
    system("PAUSE");
    return 0;
    }
    

    hier erhalte ich aber in zeile 16 den fehler:
    "void value not ignored as it ought to be"



  • zu deinem Programm:
    was willst du dort eigentlich tun? Deine Funktion gibt nichts zurück, warum versuchst du ergebnis den nicht vorhandenen Rückgabewert der Funktion zuzuweisen?
    Und das was du machst benötigt überhaupt kein Call-By-Reference und erst recht keine Pointer.
    zu Pointern & Call-By-Reference:
    Weil du eine Addresse übergibst und diese kopiert wird. Auch wenn das manchmal intern so gemacht wird, ist das auf diese Weise nicht direkt Call-By-Reference.
    Was hier auch noch fehlt: benutzt du C oder C++? Wenn du C benutzt ist die Übergabe von Pointern einem Call-By-Reference wohl am nächsten, wenn du C++ benutzt, solltest du auch Referenzen(heißt ja Call-By-Reference) und keine Pointer nutzen, es sei denn du willst nen Pointer haben.



  • ergebnis = durchschnitt(&zahl1, &zahl2); beißt sich mit void durchschnitt (int *zahl1, int *zahl2)



  • ach du scheiße jetzt versteh ich nur noch bahnhof

    in der schule würde uns an hand dieser aufgabe call by reference erklärt:

    #include <iostream>
    
    using namespace std;
    
    void Dreieckstausch (int*zeiger1, int *zeiger2) //eine call by refernce funktion beginnt mit void und nicht mit int usw.
    {
         int ihilfsfeld;
         ihilfsfeld = *zeiger1;
         *zeiger1 = *zeiger2;
         *zeiger2 = ihilfsfeld;
    
    }     
    
    int main()
    {
    
    int izahl=4, izahl2=9;
    
    cout << "Inhalt der Variablen VOR Aufruf der Funktion: " << endl << izahl << endl << izahl2 << endl;
    
    Dreieckstausch (&izahl, &izahl2);
    
    cout << "Inhalt der Variablen NACH Aufruf der Funktion: " << endl << izahl << endl << izahl2 << endl;
    
    cout << endl << endl;
    system("PAUSE");
    return 0;    
    }
    

    ich benutze c++



  • hans123 schrieb:

    //eine call by refernce funktion beginnt mit void und nicht mit int usw.
    

    das ist schon mal blanker unsinn.
    🙂


Anmelden zum Antworten