Wie verwende ich "delete" richtig?



  • Jockelx schrieb:

    Oder so:

    Dein erstes Beispiel sollte wohl new A(a,b) zurückgeben.

    Ja genau, sorry.

    A a;
    foo(&a);
    
    void foo(A* a) {
      cin >> a->a;
      cin >> a->b;
    }
    

    Also ich sollte erklären, warum ich das hässlich finde. A müsste, damit der obige Code funktioniert so aussehen:

    class A {
    public:
     A() {a = irgendwas, b=irgendwas;}
     A(int x, int y) {
     }
     int a, b;
     vec<B> v;
    };
    

    Mein Problem dazu:
    Ich brauche einen default Konstruktor und muss in diesem a,b mit irgendeinen Blödsinn initialisieren. Und dann später mit getter/setter a,b initialisieren. Das geht um das Konstruktorprinzip herum. Ein Konstruktor ist ja da, um ein Objekt in einen gültigen Zustand zu bringen. Vielleicht noch wichtiger: Initialisierungsliste von Konstruktoren: Da brauche ich, soweit ich das verstanden habe, zwingend einen Konstruktor, der gültige Werte für die Initialisierungsliste bekommt. Wie soll das mit einem Default-Konstruktor gehen??

    Jockelx schrieb:

    Code:
    A a;
    foo(a);

    void foo(A& a) {
    cin >> a.a;
    cin >> a.b;
    }

    Und das sieht gut aus.

    Das würde wegen meines obigen Problems nicht funktionieren. 🙂

    Michael E. schrieb:

    na dann miss mal. Wann werden die Objekte im vector denn kopiert? Nur dann, wenn du den vector selbst kopierst (was so gut wie nie vorkommt) und wenn der vector neuen Speicher alloziert und den alten wegwirft.

    Das heißt bei foldendem:

    vec<int> v1, v2;
    v1->push_back(30);
    v2 = v1;
    

    Werden die Element im vector nicht kopiert? Wäre ja gar nicht schlecht. Ich habe jetzt eigentlich auch gar nicht einen vector gemeint, sondern ein dynamisch angelegtes array. Und ein Array mit 3000 oder 300000 Elemente zu kopieren dauert halt lange, hab ich mir gedacht. Aber ich glaub dir, wenn du sagst, dass das schnell genug geht. 🙂

    camper schrieb:

    Sinnlos ist diese Aussage, weil völlig unspezifisch. Ich kann auch überhaupt nicht erkennen, wo die Implikation hier plötzlich herkommt. Wir kopieren doch nicht zum Spaß oder weil zufällig Speicher da ist und Zeit verschwendet werden kann, sondern deshalb, weil der verwendete Algorithmus das Anlegen einer Kopie erfordert.

    Wenn ich eben meiner Klasse A von oben verwende, und schreibe

    A a, b;
    b.v.push_back(irgendwas);
    a.v = b.v;
    

    dann habe ich mir gedacht, dass auch der gesamte Vektor kopiert wird. Wie Michael E. meint geschieht das aber nicht.

    SeppJ schrieb:

    Wenn du einmal am Programmanfang die Objekte erzeugst, wird das weniger als 0.001 % der Gesamtlaufzeit ausmachen, dafür kostet dich die Indirektion bei jedem Zugriff. Auch sonst kann (gerade in c++11) die ganze Kopiererei ganz wunderbar wegoptimiert werden. Deine Objekte werden ja sicherlich nicht selber eine sizeof von 3000 floats haben, sondern einen Verweis auf 3000 floats auf dem Heap haben, die dann gemoved werden können, was ungefähr die Kosten einer Pointerkopie hat.

    Stimmt eigentlich, an die Kosten der Indirektion hab ich noch gar nicht gedacht.

    krümelkacker schrieb:

    Diese Optimierung nennt sich RVO (return value optimization)

    Werde ich mir anchaun 🙂


  • Mod

    nightrider schrieb:

    Jockelx schrieb:

    Oder so:

    Dein erstes Beispiel sollte wohl new A(a,b) zurückgeben.

    Ja genau, sorry.

    A a;
    foo(&a);
    
    void foo(A* a) {
      cin >> a->a;
      cin >> a->b;
    }
    

    Also ich sollte erklären, warum ich das hässlich finde. A müsste, damit der obige Code funktioniert so aussehen:

    class A {
    public:
     A() {a = irgendwas, b=irgendwas;}
     A(int x, int y) {
     }
     int a, b;
     vec<B> v;
    };
    

    Mein Problem dazu:
    Ich brauche einen default Konstruktor und muss in diesem a,b mit irgendeinen Blödsinn initialisieren. Und dann später mit getter/setter a,b initialisieren. Das geht um das Konstruktorprinzip herum. Ein Konstruktor ist ja da, um ein Objekt in einen gültigen Zustand zu bringen. Vielleicht noch wichtiger: Initialisierungsliste von Konstruktoren: Da brauche ich, soweit ich das verstanden habe, zwingend einen Konstruktor, der gültige Werte für die Initialisierungsliste bekommt. Wie soll das mit einem Default-Konstruktor gehen??

    A foo()
    {
     int argument1, argument2;
     cin >> argument1 >>> argument2;
     return A(argument1, argument2);
    }
    

    Wenn dir so viele erfahrene Leute sagen, dass du kein new brauchst und es ohne viel schöner ist, dann solltest du sich ernsthaft fragen, ob du schon genug weißt, um das besser zu beurteilen.

    Das heißt bei foldendem:

    vec<int> v1, v2;
    v1->push_back(30);
    v2 = v1;
    

    Werden die Element im vector nicht kopiert?

    Hier doch. Schließlich braucht v2 die gleichen Elemente und v1 existiert weiter.

    Wäre ja gar nicht schlecht. Ich habe jetzt eigentlich auch gar nicht einen vector gemeint, sondern ein dynamisch angelegtes array.

    Noch so etwas: new für Arrays brauchst du nie! Das ist ein starkes "nie". Nimm immer vector. Ist immer besser.

    Und ein Array mit 3000 oder 300000 Elemente zu kopieren dauert halt lange, hab ich mir gedacht. Aber ich glaub dir, wenn du sagst, dass das schnell genug geht. 🙂

    Zum zehnten Mal: Du hast wahrscheinlich gar keine Kopien, sondern Verschiebungen. Wenn dein Algorithmus tatsächlich Kopien erfordern sollte, dann brauchst du eine Kopie. Da kommst du auch nicht durch Pointerindirektion herum, schließlich müsstest du immer noch kopieren. Wenn du keine Kopie brauchst, dann mach auch keine! Die Sprache zwingt dich jedenfalls nicht dazu. (Wobei es zugegebenermaßen recht einfach ist, in C++ versehentlich eine ungewollte Kopie zu machen)

    camper schrieb:

    Sinnlos ist diese Aussage, weil völlig unspezifisch. Ich kann auch überhaupt nicht erkennen, wo die Implikation hier plötzlich herkommt. Wir kopieren doch nicht zum Spaß oder weil zufällig Speicher da ist und Zeit verschwendet werden kann, sondern deshalb, weil der verwendete Algorithmus das Anlegen einer Kopie erfordert.

    Wenn ich eben meiner Klasse A von oben verwende, und schreibe

    A a, b;
    b.v.push_back(irgendwas);
    a.v = b.v;
    

    dann habe ich mir gedacht, dass auch der gesamte Vektor kopiert wird. Wie Michael E. meint geschieht das aber nicht.

    Hier wird schon kopiert. Aber da greift wieder campers Argument über sinnloses Kopieren. Das Beispiel ist vermutlich viel zu kurz, aber diese Kopie hier ist jedenfalls zum Spaß und zufällig.



  • A foo()
    {
     int argument1, argument2;
     cin >> argument1 >>> argument2;
     return A(argument1, argument2);
    }
    

    Wenn dir so viele erfahrene Leute sagen, dass du kein new brauchst und es ohne viel schöner ist, dann solltest du sich ernsthaft fragen, ob du schon genug weißt, um das besser zu beurteilen.

    Ich hab nirgends geschrieben, dass ich es besser beurteilen könnte. Ich hab halt nur nicht gewusst, wie ich einen Konstruktor aus einer Funktion heraus aufrufen soll, um ein Objekt zu initialisieren. Das hat bis jetzt noch keiner gezeigt. Am eheseten campers value-return Variante. Dein Code löst genau dieses Problem, danke!

    Noch so etwas: new für Arrays brauchst du nie! Das ist ein starkes "nie". Nimm immer vector. Ist immer besser.

    Werde ich machen.

    Ich seh schon, ich muss mir dringend ein gutes C++ Buch zulegen. 🙂

    Danke euch für die super Hilfe! Ihr seid echt spitze drauf.



  • nightrider schrieb:

    Michael E. schrieb:

    na dann miss mal. Wann werden die Objekte im vector denn kopiert? Nur dann, wenn du den vector selbst kopierst (was so gut wie nie vorkommt) und wenn der vector neuen Speicher alloziert und den alten wegwirft.

    Das heißt bei foldendem:

    vec<int> v1, v2;
    v1->push_back(30);
    v2 = v1;
    

    Werden die Element im vector nicht kopiert?

    Doch, das ist genau der erste Punkt: "wenn du den vector selbst kopierst". Genauso bei deinem zweiten Bezug auf mich.


Anmelden zum Antworten