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



  • 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.
    🙂



  • call-by-reference hat mit dem Rückgabewert gar nichts zu tun, ob das nun void oder int oder was auch immer ist hat überhaupt nichts bezüglich call-by-reference zu sagen.

    und meines Wissens nach ist das immer noch kein wirkliches Call-by-Reference, das wäre nämlich so(Die Variablennamen sind jetzt natürlich nicht mehr richtig, da es keine Zeiger mehr sind, aber ich habe alle Namen so gelassen, wie sie waren):

    #include <iostream>
    
    using namespace std;
    
    void Dreieckstausch (int& zeiger1, int& zeiger2) 
    {
         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;    
    }
    


  • hää du hast jetzt die sternchen entfernt und vor die beiden variablen ein & gesetzt

    und nun? was willst du damit sagen?!



  • dass es sich jetzt um Referenzen handelt und nicht mehr um Pointer.
    Oder glaubst du die Zeichen sind zum Spaß da?



  • JustAnotherNoob schrieb:

    dass es sich jetzt um Referenzen handelt und nicht mehr um Pointer.
    Oder glaubst du die Zeichen sind zum Spaß da?

    Desssweiteren kannst du dir beim Funktionsaufruf das & vor der Variable sparen, was zwar unübersichtlicher ist, weil du nicht mehr weißt welche variable als referenz und welche als value übergeben wird, aber auch komfortabler ist.

    Natürlich können Call-By-Ref - Funktionen auch Rückgabewerte haben!
    Behauptet dein Lehrer das gegenteil?



  • JustAnotherNoob schrieb:

    ...dass es sich jetzt um Referenzen handelt und nicht mehr um Pointer.

    nur mal so nebenbei: eine referenz ist ein verweis auf irgendwas. diese aufgabe können auch pointer erfüllen. versteift euch doch nicht immer auf eine programmiersprache, die pointer und referenzen unterscheidet.
    🙂



  • -fricky- schrieb:

    JustAnotherNoob schrieb:

    ...dass es sich jetzt um Referenzen handelt und nicht mehr um Pointer.

    nur mal so nebenbei: eine referenz ist ein verweis auf irgendwas. diese aufgabe können auch pointer erfüllen. versteift euch doch nicht immer auf eine programmiersprache, die pointer und referenzen unterscheidet.
    🙂

    Und die Pointer werde beim Call wie übergeben? 🙄



  • Tachyon schrieb:

    Und die Pointer werde beim Call wie übergeben?

    ein pointer ist eine variable. sein inhalt ist eine referenz, also die adresse z.b. einer anderen variablen. wenn man pointer an funktionen übergibt, dann übergibt man nicht den pointer selber, sondern seinen inhalt. also, ganz klar: 'by reference'. und damit keine missverständnisse aufkommen: der 'value' in diesem kontext ist nicht der inhalt des pointers, sondern das, worauf der pointer zeigt.
    🙂



  • -fricky- schrieb:

    diese aufgabe können auch pointer erfüllen.

    Was völlig unerheblich ist. Es besteht ein Unterschied "X ist ein Y" und "X kann benutzt werden, um die Funktionalität von Y zu erhalten". Jedenfalls ist der Denkansatz, dass zwei Dinge, die die gleiche Funktionalität bereitstellen, gleich sind, einer, wie er typisch für die Sprache ist, auf die hin du dich nicht versteift wissen möchtest, während er so ganz und gar nicht zu der Sprache passt, die du favorisiert, schließlich ist das auch der Ausgangspunkt für Dinge wir Funktions- und Operatorüberladung - Sachen, die aus deinem Lager so gerne als überflüssig, fehlerträchtig und überhaupt unsinnig kritisiert werden.

    C hat keine Referenzen. C braucht keine Referenzen.
    Folglich existiert in C auch keine Übergabe per Referenz, sie ist dort auch nicht notwendig. Alles andere läuft darauf hinaus, sich die Dinge zurechtzudefinieren, um in der Diskussion recht zu behalten, anstatt sich einfach mal auf die Wahrheit zu konzentrieren.



  • -fricky- schrieb:

    [...]bla[...]

    Selten so einen Unsinn gelesen.


Anmelden zum Antworten