Das ist das Ende von C++!



  • JBeni! So einen ähnlichen Test haben wir in unserer Java-Projekttruppe auch mal gemacht. Man, hab ich ins Klo gegriffen! 😃 Seit dem mache ich mir in Java darüber keine Gedanken. Wenn ich ein Objekt entgegen nehme, kann ich dessen Methoden aufrufen - fertig. Alles andere was ich aus C++ kenne, verbanne ich aus meinem Kopf, wenn ich Java mache. Denn die Kollegen von mir, die noch nie C++ gemacht haben, haben mich bei der Wette geschlagen. 😉



  • Simon2! Eben, du kannst das Objekt bzw. dessen Attribute durch setter ändern, aber mehr auch nicht.



  • ok, ganz einfach.

    fall 1:
    a und b sind kopien der referenz, d.h.
    a zeigt auf x und
    b zeigt auf y.
    so da die a und b kopien sind und dadurch call by value, verlierst du die referenzen nach beendigung der funktion.

    in deinem fall schreibst du direkt auf ein objekt, trotzdem verlierst du die referenzen a und b.

    x y
    value value (value = attribut vom object)

    so a und zeigt nun auf die selbe speicherzelle wie x. nun kannst du über a auf das
    attribut value schreiben, aber du verlierst dann denn zeiger a (aber deswegen bleibt doch das objekt erhalten).

    hoffe das ist irgendwie klar geworden.

    also zeiger auf objekt immer call-by-value

    gruß, mdoemli



  • Bashar schrieb:

    Call-by-xyz heißt, dass die Übergabe eines Argumentes beim Funktionsaufruf auf diese oder jene Art und Weise erfolgt.

    Was genau der Sichtweise entspricht, dass Du die Referenz übergibst. Schaust Du aber so drauf, dass Du das referenzierte Objekt übergibst, dann ist es call by reference.



  • ok erstens man übergibt kein objekt!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    sondern einen zeiger!!!!!!!!!!!!!!

    objekt x zeigt auf speicher-adresse 0xf321 (= value)

    so nun zeigt a auch auf 0xf321 (=value). aber a ist by-value, d.h. nach
    beendigung der funktion ist a nicht mehr da!!!!!!!!!!
    aber value schon!!!!!!!!!!!!!!!!!!!!

    wenn du nun a.value = 3;

    x.value auch 3

    gruß mdoemli



  • mdoemli schrieb:

    ok erstens man übergibt kein objekt!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    sondern einen zeiger!!!!!!!!!!!!!!

    objekt x zeigt auf speicher-adresse 0xf321 (= value)

    so nun zeigt a auch auf 0xf321 (=value). aber a ist by-value, d.h. nach
    beendigung der funktion ist a nicht mehr da!!!!!!!!!!
    aber value schon!!!!!!!!!!!!!!!!!!!!

    wenn du nun a.value = 3;

    x.value auch 3

    gruß mdoemli

    Ah, okay. Verstehe. Dann gibt es garkein call by reference. Es werden ja schließlich letztlich immer nur gewisse Speicherwerte (werte!!!!!!!!!!) an andere Speicherstellen kopiert. Also ist alles call by value!!!!!

    Un viele Ausrufezeichen helfen!!!!!!



  • Simon2 schrieb:

    Und selbst wenn ich den call-by-val für Klassentypen implementieren kann, bleibt mir der call-by-ref für primitive Typen unmöglich, oder ?

    Das man dir auch alles vorkauen muss. Wie ich bereits erwähnte liegt die Entscheidung, ob Call-By-Value vs. "Call-By-Reference" (siehe dazu später) für einen Datentyp Sinn macht, einzig und allein beim Entwickler von diesem. Im Falle von primitiven Datentypen hätte man allerdings das Problem, dass man aufgrund der Literale, die ja per Definition konstant sind, eine Außnahme einführen müsste. Ich finde ja auch in C++ ein "const int&" Schwachsinn, aber ansonsten könnte man ja kaum mehr Literale verwenden. Jetzt kommt natürlich wieder ein Argument ala "Natürlich ist es in C++ nicht gerade typisch const int& zu verwenden, allerdings ist es trotzdem möglich." 🙄 Ich hab ja auch schon dutzende Stunden wenn nicht sogar schon Tage damit verbracht ein vernünftiges swap zu schreiben .... (Ihr seht einfach Probleme, wo keine sind.)

    Sehe ich das richtig, dass Du auch der Meinung bist, der "normale Call" in Java sei call-by-ref ?

    Nein, ich bin der Meinung, dass Java kein Call-By-Reference kennt (so wie C beispielsweise auch).

    D.h. ich muß jedesmal per Hand "clonen" (auch auf die Gefahr hin, dass der Aufrufer das für mich schon getan hat) .... und dem Aufrufer das auch nur via "Doku" mitteilen, oder ?

    Weder noch, denn man kopiert einfach dann, wenn man es benötigt. Ich versteh auch nicht, was du denn dauernd so zwangsweise kopieren willst, wobei ich halt hoffe, dass es nicht diese traurige Paranoia (Mama, was ist wenn die Methode mein Objekt ändert, aber ich es nicht will? ...) ist.



  • ok sorry für die vielen ausrufezeichen.

    ne by-reference wäre z.B. wenn du schreibst

    int a = 3;
    int b = 4;

    int switch(&a, &b);

    ich wollte nur damit sagen, das man keine objekte übergibt, sondern nur zeiger.
    aber bei java hast du recht da gibt es kein call-by-reference

    gruß, mdoemli



  • mdoemli schrieb:

    ok sorry für die vielen ausrufezeichen.

    ne by-reference wäre z.B. wenn du schreibst

    int a = 3;
    int b = 4;

    int switch(&a, &b);

    ich wollte nur damit sagen, das man keine objekte übergibt, sondern nur zeiger.

    gruß, mdoemli

    Du hast meinen Einwand leider nicht verstanden. 😞

    Du argumentierst damit, ob was kopiert wird oder nicht. und ich sage, dass letztlich immer nur Werte kopiert werden und das deshalb nicht als Basis für die unterscheidung von call by value/by ref dienen kann.

    Ich finde es sollte auch nicht anhand von so syntaktischen Kleinigkeiten wie ob ein */& oder eben nix dasteht, abhängig sein sollte.



  • hallo quote experte,

    also in c gibt es auf jeden fall call-by-ref.



  • mhh, ok.
    aber bei call-by-ref wird eben nichts kopiert. das ist ja der unterschied.

    bei call-by-value macht man eine kopie und bei call-by-ref nimmt man das orginal.



  • mdoemli schrieb:

    mhh, ok.
    aber bei call-by-ref wird eben nichts kopiert. das ist ja der unterschied.

    doch, die adresse wird kopiert. Und das ist die Stelle wo man sich nun streiten kann: Wird in Java die Referenz by value übergeben, oder das referenzierte Objekte by reference?



  • quote experte schrieb:

    ...Ich versteh auch nicht, was du denn dauernd so zwangsweise kopieren willst, ...

    Merke ich.
    DAS ist der Kern meiner gesamten "primitive-Typen-Kritik": Weil primitive Typen IMMER kopiert werden, bräuchte man für eine Funktion, die dieselbe Semantik für primitive wie für Klassentypen besitzt (z.B. weil man sie als template schreiben will) eine "generalisierbare Kopiermöglichkeit für Klassentypen".

    Das bedeutet in keinster Weise, dass ich "(immer) kopieren will" ("kopieren sollte man dann, wenn man es braucht") .... sondern, dass ich für alle Typen die Möglichkeit haben möchte, sie mit der Kopiersemantik zu übergeben.
    Oder (besser beides): Dass ich für alle Typen die Möglichkeit haben möchte, sie mit der Referenzsemantik zu übergeben (also auch für primitive Typen).
    - zumindestens, wenn man templates konsistent einführen möchte.

    Gruß,

    Simon2.



  • mdoemli schrieb:

    ...
    ne by-reference wäre z.B. wenn du schreibst

    int a = 3;
    int b = 4;

    int switch(&a, &b);
    ...

    Und dafür gilt das Folgende nicht ?

    mdoemli schrieb:

    ok erstens man übergibt kein objekt!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    sondern einen zeiger!!!!!!!!!!!!!!

    objekt x zeigt auf speicher-adresse 0xf321 (= value)

    so nun zeigt a auch auf 0xf321 (=value). aber a ist by-value, d.h. nach
    beendigung der funktion ist a nicht mehr da!!!!!!!!!!
    aber value schon!!!!!!!!!!!!!!!!!!!!

    wenn du nun a.value = 3;

    x.value auch 3

    gruß mdoemli

    Da übergibst Du doch auch nur "ein 0xf0321" ....

    Gruß,

    Simon2.



  • Ich finde es sollte auch nicht anhand von so syntaktischen Kleinigkeiten wie ob ein */& oder eben nix dasteht, abhängig sein sollte.

    // C++ 
    void foo(Bar* baz) {
        baz = new Bar;
    } // baz bleibt beim Aufrufer vor und nach der Funktion gleich -> Call-By-Value
    
    void foo(Bar& baz) {
        baz = new Bar; // ich weiß das wohl syntaktisch nicht korrekt ist
    } // baz ist nach dem Funktionsaufruf verändert
    

    Egal wie man es dreht oder wendet im 2. Fall arbeitet man immer mit dem Original. Die Übergabe eines Zeigers als Call-By-Reference zu erklären, halt ich für falsch. Dann müsste ja folgender Typ auch ein "reiner Referenzdatentyp" sein.

    class Foo {
        private:
            Bar* bar = new Bar;
    
        public:
            void bla() {
                bar->moo();
            }
    }
    

    Auch hier kannst du soviel "kopieren", wie du willst, du arbeitest im Wesentlichen eigentlich immer mit der selben Instanz (hängt jetzt natürlich davon ab, wie man die Identität definiert.)



  • Das bedeutet in keinster Weise, dass ich "(immer) kopieren will" ("kopieren sollte man dann, wenn man es braucht") .... sondern, dass ich für alle Typen die Möglichkeit haben möchte, sie mit der Kopiersemantik zu übergeben.

    Um dir das anders zu verdeutlichen: Durchsuch einfach mal Open-Source Java Projekte (beispielsweise von der Apache Foundation) und such nach dem Methodenaufruf clone() um zu erfahren, wie sehr man Kopien in der Java Entwicklung benötigt. Um dir etwas Arbeit abzunehmen habe ich einfach mal Apache Shale hergenommen und rate mal auf wieviele Treffer ich gekommen bin. 0. Wie gesagt, du bildest dir die Probleme einfach nur ein.

    Oder (besser beides): Dass ich für alle Typen die Möglichkeit haben möchte, sie mit der Referenzsemantik zu übergeben (also auch für primitive Typen). - zumindestens, wenn man templates konsistent einführen möchte.

    "Referenzsemantik" wird doch sowieso für primitive Datentypen auch geboten, du musst ja nur die Wrapper verwenden. Wo ist denn bei Generics eine Inkonsistenz? Schreib doch einfach Integer statt int, musst es ja nur bei der Deklaration machen und es wurden dadurch weder Kompatibiltäten gebrochen noch Komplexitäten geschaffen. Wenn du diese Lösung nicht akzeptieren willst, kannst du ja gleich auch argumentieren "Aber Java ist nicht C++, deshalb ist Java schlecht .." ...



  • Jester schrieb:

    doch, die adresse wird kopiert. Und das ist die Stelle wo man sich nun streiten kann: Wird in Java die Referenz by value übergeben, oder das referenzierte Objekte by reference?

    Mein Argument ist folgendes: Man kann in Java Objekte überhaupt nicht direkt anfassen, sondern immer nur per Referenz. Man arbeitet immer nur durch die Referenz mit dem Objekt. Egal, ob man die Referenz jetzt einer Funktion übergibt oder zurückgibt oder einer Variablen zuweist. Ich finde diese Sichtweise logisch und systematisch sehr sauber. Man findet sowas auch in anderen Sprachen, ich sag jetzt nur mal Lisp, wo alles by-value übergeben wird, auch wenn es sich bei den Werten in den meisten Fällen um verkappte Zeiger handelt.
    .NET geht dann übrigens noch einen Schritt weiter und erlaubt tatsächlich die Übergabe von (u.a.) Objektreferenzen by-reference. Wie will man sowas verstehen, wenn man sich mit Sonderfallunterscheidungen zwischen primitiven und Klassentypen, die im Grunde künstlich und sinnlos sind, herumschlägt?

    Irgendwer hatte auch die Zeigerübergabe in C als Beispiel angesprochen. Das ist relativ einfach IMHO, man simuliert dadurch eine Übergabe by-reference, aber man macht eine Übergabe by-value.

    Die Referenztypen von C++ sind die echte Schwierigkeit. 🙂



  • Zeus schrieb:

    Optimizer schrieb:

    In C# würde es T oder ref T heißen.

    In C# muss du nur Werttype als ref übergeben, sonst auch nicht.

    Das stimmt so nicht. Wenn du Ref bei Wertetypen anwendest wird die Referenz übergeben. Wenn du Ref bei Referenztypen anwendest wird die Referenz auf die Referenz übergeben, so das du die Referenz ändern kannst.



  • Mein Trollbeitrag hat jetzt schon 21 Seiten 🕶



  • Zwergli schrieb:

    Zeus schrieb:

    Optimizer schrieb:

    In C# würde es T oder ref T heißen.

    In C# muss du nur Werttype als ref übergeben, sonst auch nicht.

    Das stimmt so nicht. Wenn du Ref bei Wertetypen anwendest wird die Referenz übergeben. Wenn du Ref bei Referenztypen anwendest wird die Referenz auf die Referenz übergeben, so das du die Referenz ändern kannst.

    ops wieder dazugelernt 🙂


Anmelden zum Antworten