Kopien und Zuweisungen von Klassenobjekten



  • damit sich auch was im vektor wirklich ändert musst du ihn per call-by-reference statt per call-by-value übergeben:

    void tuwas(std::vector<A*>& boo) {  // <- das & steht in dem kontext für eine referenz
        // ...
    }
    


  • Arcoth schrieb:

    Nein. Um die Lebenszeit des Objektes dynamisch zu machen, nutzt man new .

    boo.push_back( new A(1,2) );
    

    Allerdings gibt es hier ein Problem: Wann wirst du den Speicher wieder freigeben?

    gnah .. keine guten Nachrichten 🙂
    ich könnte das natürlich am Ende von main mit delete wieder freigeben ... Ich muss dann aber auch nur die letzten Elemente vom Vector freigeben. Der ganzen Vector darf ich ja nicht anfassen. Dann müsste ich mir zusätzlich merken, wieviele neuen Elemente ich mit new geholt habe ... das ist ja eklig ^^

    Noch weitere Vorschläge? 😃

    afasfasfa schrieb:

    damit sich auch was im vektor wirklich ändert musst du ihn per call-by-reference statt per call-by-value übergeben:

    void tuwas(std::vector<A*>& boo) {  // <- das & steht in dem kontext für eine referenz
        // ...
    }
    

    AAHHH ... wie banane .. 😃
    DANKE! 😃



  • Lymogry schrieb:

    Noch weitere Vorschläge? 😃

    eigenen allocator schreiben



  • adfasdfad schrieb:

    Lymogry schrieb:

    Noch weitere Vorschläge? 😃

    eigenen allocator schreiben

    Du meine Güte ... 😉

    Call by Reference hats schon getan ... darauf bin ich nicht mehr gekommen, nachdem ich Sternchen gesehen habe! 😃
    (Warst du das nicht gerade eben?)



  • Lymogry schrieb:

    Call by Reference hats schon getan ... darauf bin ich nicht mehr gekommen, nachdem ich Sternchen gesehen habe! 😃

    pass auf, gleich kommt sone und sagt dir dass das beides call-by-value ist!

    Lymogry schrieb:

    (Warst du das nicht gerade eben?)

    ja weil ich unkreativ bin bzgl. namenswahl.



  • asfasdfas schrieb:

    Lymogry schrieb:

    Call by Reference hats schon getan ... darauf bin ich nicht mehr gekommen, nachdem ich Sternchen gesehen habe! 😃

    pass auf, gleich kommt sone und sagt dir dass das beides call-by-value ist!

    hihihi 😃
    Wir warten! 🙂



  • Ok ... zu früh gefreut????

    void tuwas(std::vector<A*> &boo) {
        A foo3(9,10);
        boo.push_back(&foo3);   // Neues Element als Platzhalter.
        *(boo[boo.size()-1])=foo3;  // Inhalt kopieren. Geht nicht!
    }
    

    Und das in main:

    std::vector<A*> boo;
        boo.push_back(&foo[0]);
        std::cout << boo[0]->getX() << " " << boo[0]->getY() << "  \n";
        wechseln2(boo);
        std::cout << boo[0]->getX() << " " << boo[0]->getY() << " <- Inhalt kopieren geht!  \n";
        std::cout << "foo.size()=" << boo.size() << "\n";
        tuwas(boo);
        std::cout << "nach tuwas: boo.size()=" << boo.size() << " <- wird größer  \n";
        std::cout << boo[1]->getX() << "Inhalt stimmt nicht! \n" ;
    

    Edit: da stand vorhin eine falsche Funktion 😉



  • du übergibst einen pointer auf ein lokales objekt, das ist böse.
    wusste nicht, dass du sowas machen willst. mach einfach einen vector aus A statt aus zeigern auf A. ansonsten musst du wohl oder übel (eher übel) einen allocator machen oder einen vector aus smart_ptr<A> machen. willst du beides nicht da es dir keine vorteile bringt. tl;dr -> std::vector<A>

    "Inhalt stimmt nicht"

    ja, der zeiger zeigt auf eine stelle im speicher an der nichts ist. undefiniertes verhalten. böse.



  • du übergibst einen pointer auf ein lokales objekt, das ist böse.
    

    Ja, deswegen jammer ich schon auf der letzten Seite ... 😃
    Es geht ja um den temporären Speicher. Wenn ich den in main hole und dann in einer Subroutine den Inhalt wechsel, ists kein Problem. Aber ich kann in einer Subroutine nicht die Größe des Arrays ändern ...

    wusste nicht, dass du sowas machen willst. mach einfach einen vector aus A statt aus zeigern auf A.
    

    Nun, warum ich das unbedingt mit Pointern lösen will:
    Die Klasse A hat noch abgeleitete Klassen. Und alle Elemente von A und deren Ableitungen sollen in ein Array rein. Ich möchte mir aber merken, welcher Typ jetzt drin ist. Wenn ich nur das Array über A laufen lassen, ist zwar alles drin, aber der Ableitungstyp geht verloren ...



  • ja dann mach es mit smart pointer:

    #include <iostream>
    #include <vector>
    #include <memory>
    #include <string>
    #include <sstream>
    struct base
    {
    	int a;
    	explicit base(int a = 0)
    		: a(a)
    	{
    	}
    	virtual std::string str() const
    	{
    		std::ostringstream mybuf;
    		mybuf << "i'm a base(" << this->a << ")\n";
    		return mybuf.str();
    	}
    };
    struct derived : base
    {
    	int b;
    	explicit derived(int a = 0, int b = 0)
    		: base(a), b(b)
    	{
    	}
    	virtual std::string str() const
    	{
    		std::ostringstream mybuf;
    		mybuf << "i'm derived(" << this->a << ", " << this->b << ")\n";
    		return mybuf.str();
    	}
    };
    typedef std::vector<std::shared_ptr<base>> container_type;
    void add_base(container_type& vec)
    {
    	vec.push_back(typename container_type::value_type(new base(5)));
    }
    void add_derived(container_type& vec)
    {
    	vec.push_back(typename container_type::value_type(new derived(2, 7)));
    }
    int main()
    {
    	container_type myvec;
    	add_base(myvec);
    	add_derived(myvec);
    	std::cout << "there are " << myvec.size() << " entries, they're:\n";
    	std::cout << myvec[0]->str() << myvec[1]->str();
    }
    

    braucht c++11 support. std::shared_ptr weist relativ intuitives kopier-/zuweisungsverhalten auf. naja nicht ganz, wenn du ein shared_ptr einem anderen zuweist, dann zeigen beide auf das selbe objekt. das zweite objekt ist dann auch noch gültig wenn das erste zerstört wurde (so dass man den besitz über scopes hinweg weitergeben kann). dass ein objekt den fundamentalen regeln zum kopieren usw unterliegt ist anforderung dafür, dass es in stl-containern (z.b. vector) abgelegt werden kann. um das delete kümmert sich shared_ptr selbst.



  • braucht c++11 support. std::shared_ptr weist relativ intuitives kopier-/zuweisungsverhalten auf. naja nicht ganz, wenn du ein shared_ptr einem anderen zuweist, dann zeigen beide auf das selbe objekt. das zweite objekt ist dann auch noch gültig wenn das erste zerstört wurde (so dass man den besitz über scopes hinweg weitergeben kann). dass ein objekt den fundamentalen regeln zum kopieren usw unterliegt ist anforderung dafür, dass es in stl-containern (z.b. vector) abgelegt werden kann. um das delete kümmert sich shared_ptr selbst.

    ganz schön mächtig! 😮
    Da muss ich mich erst einarbeiten, um das Nachzuvollziehen. Vielen Dank! 🙂

    Was genau ist denn davon C++11? Das ganze Prinzip oder nur teilweise einige Funktionen?
    (Mein Compiler kanns zwar, ... interesse! 🙂 )



  • Lymogry schrieb:

    braucht c++11 support. std::shared_ptr weist relativ intuitives kopier-/zuweisungsverhalten auf. naja nicht ganz, wenn du ein shared_ptr einem anderen zuweist, dann zeigen beide auf das selbe objekt. das zweite objekt ist dann auch noch gültig wenn das erste zerstört wurde (so dass man den besitz über scopes hinweg weitergeben kann). dass ein objekt den fundamentalen regeln zum kopieren usw unterliegt ist anforderung dafür, dass es in stl-containern (z.b. vector) abgelegt werden kann. um das delete kümmert sich shared_ptr selbst.

    ganz schön mächtig! 😮
    Da muss ich mich erst einarbeiten, um das Nachzuvollziehen. Vielen Dank! 🙂

    Was genau ist denn davon C++11? Das ganze Prinzip oder nur teilweise einige Funktionen?
    (Mein Compiler kanns zwar, ... interesse! 🙂 )

    jaaa!

    was davon c++11 ist? std::shared_ptr und das ">>" in zeile 34 (wäre in c++03 "> >")



  • hmm .... ich weiß jetzt auch ganz genau wo C++11 ist 😃
    Weil: compiliert nicht! Obwohl es der aktuellste MinGW 4.8.1 in cygwin ist, der theoretisch C++11 kann!
    Theoretisch ... ich sehe im Internet gerade, dass ich nicht allein mit dem Problem bin ... 😕
    Ist jetzt wohl ein Problem für das Compilerforum ... 👎



  • mein code oder dein code?
    denn mein gepostetes codebeispiel funktioniert bei ideone.com mit c++11-einstellung. wenn deiner nicht kompiliert, kannst du ihn mal in der überarbeiteten version posten...



  • Compilerflag std=c++11.



  • Nein, ich wollte deinen Code compilieren.
    Ich suche noch, wie ich MinGW bzw Cygwin einstelle, damit er C++11 kompiliert. Angeblich kennt er es ja ...


  • Mod

    pass auf, gleich kommt sone und sagt dir dass das beides call-by-value ist!

    Nein, der behauptet das Gegenteil, hättest du mal aufgepasst.



  • Nathan schrieb:

    Compilerflag std=c++11.

    AH!
    Ja, Danke Nathan! So gehts! 🙂

    PS für alle, die es auch wissen wollen:
    CYGWIN
    g++ -Wall -pedantic -std=c++11 -o main.exe main.cpp



  • HAHAHA .. guck mal auf was für eine lustige Idee ich gekommen bin: 😃

    #include <iostream>
    #include <vector>
    
    class A {
    public:
        A(const int dx, const int dy) : x(dx), y(dy) {}
        A(const A& einA) :x(einA.x), y(einA.y) {}
        A &operator=(A einA)  {swapi(einA); return *this;}
        void swapi(A& einA);
        int getX() const {return x;}
        int getY() const {return y;}
    
    private:
        int x;
        int y;
    };
    
    void A::swapi(A& einA) {
        std::swap(x,einA.x);
        std::swap(y,einA.y);
    }
    
    void tuwas(std::vector<A*> &foo, std::vector<A> &miststueck) {
        miststueck.push_back(A(2,3));
        foo.push_back(&miststueck[miststueck.size()-1]);
        *(foo[miststueck.size()-1])=miststueck[miststueck.size()-1];
    }
    
    int main() {
        std::vector<A*> foo;
        std::vector<A> miststueck;  // dem klau ich den Speicher!
        A tmp(A(1,1));
        foo.push_back(&tmp);
        std::cout << foo[0]->getX() << " " << foo[0]->getY() << "\n";
        tuwas(foo, miststueck);
        std::cout << foo[1]->getX() << " " << foo[1]->getY() << "\n";
        std::cout << miststueck[0].getX() << " " << miststueck[0].getY() << "\n";
        return 0;
    }
    

    Was sagst du dazu? 🤡



  • lol, gute idee. aber: stichwort: iterator validity

    wenn du den vector veränderst (vergrösserst usw) muss u.U. neuer speicher reserviert werden. dann werden deine alten zeiger ungültig...


Anmelden zum Antworten