Referenzen als Klassen Member



  • Dieser Beitrag wurde gelöscht!


  • Hallo,

    stwe schrieb:

    Und warum geht das hier in die Hose?:

    das sagt dir doch dein Kompiler:
    Er weiss nicht, wie er ein Mesh konstruieren soll (findet keinen passenden Konstruktor).

    Ist dir klar, dass

    class A
    {
      Mesh  mValue; // hier eine Kopie erzeugt wird
      Mesh & mRef // hier nur eine Referenz auf ein bestehendes Objekt erzeugt wird?
    
    // genauso bei Funktionen/Konstruktoren
      void f(Mesh& m) // hier wird erstmal gar nix kopiert
      {
         mValue = m;  // jetzt schon
      }
      void f2(Mesh m) // hier wird kopiert
      {
         mValue = m;  // und hier
      }
      A(Mesh& m) : mRef {m}, // keine Kopie
                   mValue {m} {} // kopiert
      {};
    
    // Beispiel würde natürlich nur funktionieren, wenn Mesh die entsprechenden Konstruktoren hätte.
    


  • stwe schrieb:

    Ist es per se eine gute Idee, alles im Ctor, was gleichzeitig Klassenmember ist, als Referenz (ja, ich weiß, es gibt auch Zeiger, aber darum geht es hier nicht) zu übergeben? Also ist das hier best practice?:

    class Mesh
        {
        public:
            Mesh(std::vector<Vertex> & vertices, std::vector<unsigned int> & indices, std::vector<Texture> & textures);
            virtual ~Mesh();
    
        private:
    
            std::vector<Vertex> & m_vertices;
            std::vector<unsigned int> & m_indices;
            std::vector<Texture> & m_textures;
        };
    

    Das ist meistens genau nicht das was man haben möchte, da so ein Konstrukt (reference-member) ein sehr unerwartetes Verhalten zeigt. Da eben nur Referenzen auf die eigentlichen Daten gespeichert werden, nicht aber die Daten ansich. Wenn die original Daten dann z.B. out-of-scope gehen, dann sind die Referenzen ungültig und es knallt. Und noch schlimmer: Wenn du zwei Instanzen a und b von Mesh machst, die auf unterschiedliche Daten verweisen, und dann "a = b;" schreibst, dann werden die original Daten mit denen a initialisiert wurde geändert!

    Bis auf sehr spezielle Hilfskonstrukte wie [c]boost::tie[/c] hat das kaum eine sinnvolle Anwendung.

    Bei "nicht zuweisbaren" Klassen (wo also das "a = b;" gar nicht geht) kann es OK sein, nur würde ich trotzdem eher empfehlen Zeiger Member statt dessen zu verwenden.
    EDIT: Unsinn der auf der falschen Annahme beruht dass Klassen die (non-static) Referenzen als Member haben einen Default Assignment Operator bekommen würden. /EDIT

    stwe schrieb:

    Warum lässt sich sowas hier fehlerfrei übersetzen?: Die Member sind jetzt keine Referenz, aber über den Ctor. sind sie das schon. Wie geht das?

    class Mesh
        {
        public:
            Mesh(const std::vector<Vertex> & vertices, const std::vector<unsigned int> & indices, const std::vector<Texture> & textures);
            virtual ~Mesh();
    
        private:
    
            std::vector<Vertex> m_vertices;
            std::vector<unsigned int> m_indices;
            std::vector<Texture> m_textures;
        };
    

    Öh, ... wieso sollte es nicht gehen? Das ist eine "ganz normale" Sache. Ich würde sagen jetzt wäre es an der Zeit mal C++ zu lernen 😉
    Also speziell eben die Sache mit den Referenzen, wozu die gut sind, wie sie sich verhalten etc.

    stwe schrieb:

    Und warum geht das hier in die Hose?:

    class Entity
        {
        public:
            explicit Entity(Mesh mesh)
                : m_mesh{ mesh }
            {};
    
        private:
            Mesh m_mesh;
            
            // ...
    
        };
    

    Danke vorab.

    Definiere "geht in die Hose".

    ps: Ist dir klar dass Referenzen in C++ etwas ganz anderes sind als in Java?



  • hustbaer schrieb:

    Bis auf sehr spezielle Hilfskonstrukte wie boost::tie hat das kaum eine sinnvolle Anwendung.

    Na ja, soo speziell ist das nun auch wieder nicht.
    Jedes Lambda macht sowas by default.

    hustbaer schrieb:

    Bei "nicht zuweisbaren" Klassen (wo also das "a = b;" gar nicht geht) kann es OK sein, nur würde ich trotzdem eher empfehlen Zeiger Member statt dessen zu verwenden.

    Warum?
    Warum sollte man das in Klassen anders handhaben, als bei Funktionen (Pointer optional, Referenz muss da sein)?



  • Jockelx schrieb:

    hustbaer schrieb:

    Bis auf sehr spezielle Hilfskonstrukte wie boost::tie hat das kaum eine sinnvolle Anwendung.

    Na ja, soo speziell ist das nun auch wieder nicht.
    Jedes Lambda macht sowas by default.

    IIRC werden "by reference" eingefangene Variablen als Zeiger-Member in der generierten Klasse gespeichert. Weil es eben gerade keinen Sinn macht wirklich Referenz-Member zu nehmen.
    Ich meine das mal wo gelesen zu haben. Muss aber erst nochmal googeln ob ich das wieder finde - wozu ich aber jetzt direkt keine Zeit habe.

    Jockelx schrieb:

    hustbaer schrieb:

    Bei "nicht zuweisbaren" Klassen (wo also das "a = b;" gar nicht geht) kann es OK sein, nur würde ich trotzdem eher empfehlen Zeiger Member statt dessen zu verwenden.

    Warum?
    Warum sollte man das in Klassen anders handhaben, als bei Funktionen (Pointer optional, Referenz muss da sein)?

    Überleg dir einfach mal was passiert wenn man ("assignable") Klassen macht die (non-const) Referenzen als Member enthalten... und Instanzen davon dann zuweist (operator =). Bzw. lies es nach, ich hab ja schon beschrieben was passiert. Und was passiert ist ganz 'was anderes als was passiert wenn man es mit Zeigern machen würde.
    Und das Ergebnis das man üblicherweise möchte ist das was man mit Zeigern bekommt, nicht das was man mit Referenzen bekommt.

    Verstehe nicht was daran so schwer zu verstehen ist. Also angenommen du weisst was boost::tie ist, was es macht und wie es das macht. Und da du auf meine boost::tie Bemerkung geantwortet hast, solltest du das wissen.



  • hustbaer schrieb:

    IIRC werden "by reference" eingefangene Variablen als Zeiger-Member in der generierten Klasse gespeichert. Weil es eben gerade keinen Sinn macht wirklich Referenz-Member zu nehmen.
    Ich meine das mal wo gelesen zu haben. Muss aber erst nochmal googeln ob ich das wieder finde - wozu ich aber jetzt direkt keine Zeit habe.

    Das glaube ich gerne, dass du da keine Zeit für hast.
    Google 'c++ lambda generated code' liefert auch nur Beispiele, die genau das Gegenteil von dem von dir behaupteten zeigen.
    Musst du wohl lange suchen, um eine Bestätigung zu kriegen...

    Jockelx schrieb:

    hustbaer schrieb:

    Bei "nicht zuweisbaren" Klassen (wo also das "a = b;" gar nicht geht) kann es OK sein, nur würde ich trotzdem eher empfehlen Zeiger Member statt dessen zu verwenden.

    ...
    Überleg dir einfach mal was passiert wenn man ("assignable") Klassen macht

    Liest du auch was du selber schreibst?



  • Jockelx schrieb:

    Jockelx schrieb:

    hustbaer schrieb:

    Bei "nicht zuweisbaren" Klassen (wo also das "a = b;" gar nicht geht) kann es OK sein, nur würde ich trotzdem eher empfehlen Zeiger Member statt dessen zu verwenden.

    ...
    Überleg dir einfach mal was passiert wenn man ("assignable") Klassen macht

    Liest du auch was du selber schreibst?

    Klar.
    Nur ohne die Annahme dass du diesen Teil ignoriert hast macht deine Antwort gleich überhaupt keinen Sinn mehr. Warum sollte man in non-assignable Klassen die Member anders machen als in assignable Klassen?

    Referenzen als Member sind strange und man kann sich schnell damit in den Fuss schiessen. Klar, kann man machen.

    Davon abgesehen wird mir das hier ein bisschen zu doof.


  • Mod

    hustbaer schrieb:

    Jockelx schrieb:

    hustbaer schrieb:

    Bis auf sehr spezielle Hilfskonstrukte wie boost::tie hat das kaum eine sinnvolle Anwendung.

    Na ja, soo speziell ist das nun auch wieder nicht.
    Jedes Lambda macht sowas by default.

    IIRC werden "by reference" eingefangene Variablen als Zeiger-Member in der generierten Klasse gespeichert.

    Das ist nicht vorgegeben. Und im Grunde ist es auch egal, weil closure Typen sowieso nicht zuweisbar sind (und copy ctors haben kein Problem mit Referenzen).

    Edit: Im Übrigen schließe ich mich dem Vorschlag an, auf Referenzen als Member per se zu verzichten. Bei Zeigern ist das const explizit (oder eben nicht vorhanden), und die Semantik kann intuitiver sein. Schlussendlich läuft diese Diskussion aber doch sowieso auf quod licet Iovi, non licet bovi hinaus!



  • Ja, es ist egal. Nachdem ich jetzt nachgelesen habe und nun auch weiss dass Lambdas nicht zuweisbar sind... ist mir das auch klar 🙂

    Jockelx hat mich hier (absichtlich?) auf die falsche Fährte gelockt indem er Lambdas als Beispiel für Referenzen in zuweisbaren Klassen (wie eben boost::tie ) gebracht hat.
    Was natürlich quatsch ist.
    Weil Lambdas ja nicht zuweisbar sind.

    Meine aber trotzdem mich zu erinnern dass im Standard stand dass sich die Lambdas so verhalten sollen als ob sie einen Zeiger auf die "by reference" eingefangenen Objekte enthalten würden, und die Objekte über diesen ansprechen.

    EDIT:

    und copy ctors haben kein Problem mit Referenzen

    op = hat da auch kein Problem mit. Nur der Programmierer hat dann u.U. ein Problem wenn sein Programm auf einmal ganz 'was anderes macht als er eigentlich wollte. 😉



  • hustbaer schrieb:

    Jockelx hat mich hier (absichtlich?) auf die falsche Fährte gelockt

    Ja, genau... 🙄

    hustbaer schrieb:

    Davon abgesehen wird mir das hier ein bisschen zu doof.

    Ja, war mir spätestens hier

    hustbaer schrieb:

    Verstehe nicht was daran so schwer zu verstehen ist

    eigentlich auch schon zu blöd, mit dir zu diskutieren.



  • Dieser Beitrag wurde gelöscht!


  • stwe schrieb:

    Ist obiges hier normaler Umgangston?

    Ging doch nicht gegen dich.
    Und wie ich hustbaer einschätze, wird der -genauso wie ich- jetzt auch nicht deshalb schlecht einschalfen heute nacht.

    stwe schrieb:

    Als Ergebnis nehme ich mal dieses hier mit:

    Im Übrigen schließe ich mich dem Vorschlag an, auf Referenzen als Member per se zu verzichten. Bei Zeigern ist das const explizit (oder eben nicht vorhanden), und die Semantik kann intuitiver sein.

    Ja, aber insbesondere die ersten beiden Antworten, weil die erklären, was du offenbar falsch verstanden hast.


  • Mod

    hustbaer schrieb:

    und copy ctors haben kein Problem mit Referenzen

    op = hat da auch kein Problem mit.

    Doch.


  • Mod

    stwe schrieb:

    Ist obiges hier normaler Umgangston?

    Lass mich direkt aus der Bibel zitieren:

    Vieles, das wie Grobheit aussieht, ist in Hacker-Kreisen nicht als Beleidigung gedacht. Es ist im Gegenteil das Produkt einer direkten Art der Kommunikation ohne Umschweife, die Personen zu eigen ist, die mehr daran interessiert sind, Probleme zu lösen, als andere sich liebgehabt und geborgen fühlen zu lassen.

    Wenn dir rohes Verhalten entgegengebracht wird, reagiere gelassen. Wenn jemand wirklich übertreibt, wird ihn sehr wahrscheinlich ein alter Hase in der Gruppe zurechtweisen. Wenn das nicht passiert und du deine Beherrschung verlierst, hat die betreffende Person sich wahrscheinlich an die in der Gruppe herrschenden Regeln gehalten, und du dich falsch benommen. Das wird deine Chance auf kompetente Hilfe verringern.

    Auf der anderen Seite wirst du gelegentlich auf sinnlose oder ungerechtfertigte Rüpelhaftigkeit stoßen. Die andere Seite des oben Gesagten ist, dass es akzeptiertes Verhalten ist, wirklich ausfallende Personen hart zurechtzuweisen und deren falsches Benehmen mit scharfem Messer verbal zu sezieren. Sei dir deines Grundes deshalb sehr sehr sicher, bevor du so etwas tust. Der Grat zwischen dem Korrigieren eines Missgriffs und dem Lostreten eines endlosen Flamewars ist schmal genug, dass selbst Hacker ihn gelegentlich übertreten; wenn du ein Neuling oder ein Außenseiter bist, stehen die Chancen schlecht, eine solche Übertretung zu vermeiden. Wenn du auf Informationen aus bist und nicht auf Unterhaltung, dann ist es besser, du lässt die Finger von der Tastatur, anstatt so etwas zu riskieren.

    (Manche Leute behaupten, dass viele Hacker an einer schwachen Form von Autismus oder des Aspergerschen Syndroms leiden, und ihnen einige der Hirnwindungen fehlen, welche die 'normalen' zwischenmenschlichen Beziehungen steuern. Das mag stimmen oder auch nicht. Wenn du selber kein Hacker bist, kann es dir helfen, unsere Exzentrizitäten als die von geistig Gestörten anzusehen. Sieh darüber hinweg. Uns macht das nichts aus; uns gefällt die Art, wie wir sind, und normalerweise haben wir ein gesundes Misstrauen klinischen Bezeichnungen gegenüber.)



  • Arcoth schrieb:

    hustbaer schrieb:

    und copy ctors haben kein Problem mit Referenzen

    op = hat da auch kein Problem mit.

    Doch.

    Oha!
    Danke für die Korrektur.
    Ich war überzeugt davon dass das geht. Peinlich.

    D.h. bei tuple<> funktioniert das nur, weil tuple<> selbst einen entsprechenden Assignment-Operator definiert.
    Peinlich.



  • @Jockelx
    Wusstest du dass der Assignment-Operator nicht automatisch definiert wird? Falls ja hättest du mich einfach auf meinen Fehler hinweisen können. Aber OK, vielleicht war aus meinem Beitrag auch nicht klar dass ich das annehme - ich hätte ja auch meinen können dass man selbst einen definiert.

    Dadurch dass hier nicht ohne Zutun des Programmierers Unfug passieren kann fällt nämlich der wichtigste Punkt der mMn. gegen Referenzen als Member gesprochen hätte weg. Nicht dass ich die Idee jetzt toll finde -- muss erst nochmal drüber nachdenken und das neu bewerten.

    Und ja, ich werde keine schlaflosen Nächte deswegen.



  • Dieser Beitrag wurde gelöscht!

  • Mod

    stwe schrieb:

    Daher und als Hinweis für das nächste mal: mir hätte auch ein einfaches "Ja" gereicht.

    Aber ich habe deine Frage doch gar nicht bejaht. Der Umgangston war nicht einer, den wir hier in jedem zweiten Thread zu sehen erwarten, aber einer, an dem wir uns auch nicht stören.



  • Ich denke, ich habe den TO richtig verstanden. Persönlich hat er sich nicht angegriffen gefühlt, sondern sich gewundert, das sich gestandene Forenteilnehmer mit doof etc titulieren. Darauf die Frage, ob das hier normal sei.

    Da hilft auch keine Hackerbibel, denn solche Auseinandersetzungen erwartet man vielleicht im politischen Bereich, aber eben nicht unter Geistesarbeitern.


Anmelden zum Antworten