Entfernen eines bestimmten Elements aus einem Vector



  • drakon schrieb:

    Die werden ja kopiert.. 😕

    Eben deshalb frage ich ja. In Java würde das Objekt soviel ich weiss nicht kopiert.

    drakon schrieb:

    Das glaube ich kaum.. Das wird i.d.R wegoptimiert. 😉

    Aha, sich einfach mal von vornherein drauf verlassen, dass der Compiler super wegoptimieren kann, anstatt einen gleichwertigen Fall zu nehmen, bei dem nichts optimiert werden muss? 🙄

    Es ist vorgesehen, dass in dem Fall ein temporäres Objekt erzeugt wird. Gewisse Umstände verhindern auch ein Wegoptimieren. Bau zum Beispiel mal ein Logging in den Konstruktor ein; ich will sehen, ob man von der erstellten Klasse nichts mitbekommt.



  • Du willst ja schon, dass die Device-Einträge kopiert werden und nicht nur Verweise im std::vector gespeichert sind, oder? Denn in diesem Fall müsstest du Zeiger einsetzen.

    Wenn da anstatt "in diesem Fall" "andernfalls" gestanden wäre, hätte ichs verstanden. 😉

    Nexus schrieb:

    Es ist vorgesehen, dass in dem Fall ein temporäres Objekt erzeugt wird. Gewisse Umstände verhindern auch ein Wegoptimieren. Bau zum Beispiel mal ein Logging in den Konstruktor ein; ich will sehen, ob man von der erstellten Klasse nichts mitbekommt.

    Das ist afaik eine sehr gängige und übliche Optimierung.

    struct foo
    {
     foo ()
     {
      std::cout << "ctor-foo" << std::endl;
     }
    };
    
    int main ()
    {
     foo f = foo ();
    }
    

    Ausgabe:

    ctor-foo
    


  • drakon schrieb:

    Wenn da anstatt "in diesem Fall" "andernfalls" gestanden wäre, hätte ichs verstanden. 😉

    Stimmt, war etwas missverständlich. Ich bezog mich mit "diesem" auf das letzgenannte (hier die Verweise). 😉

    drakon schrieb:

    Das ist afaik eine sehr gängige und übliche Optimierung.

    Das dachte ich mir fast, aber dass das Verhalten des Programms verändert wurde, wusste ich nicht (ich kann deine Ausgabe bestätigen). Denn eigentlich müsste streng genommen ein temporäres Objekt erzeugt werden, oder? Zumindest dachte ich, es wäre nicht erlaubt, dass die Optimierung das Programmverhalten ändert...



  • Nexus schrieb:

    Denn eigentlich müsste streng genommen ein temporäres Objekt erzeugt werden, oder?

    Ja, so ist es. Ohne Optimierung würde ein Konstruktor und anschließend der Copy-Konstruktor aufgerufen. Wenn du den Copy-Konstruktor private deklarierst, dann scheitert auch die ganze Geschichte, im Gegensatz zur Direct-Initialisierung wo ja von Beginn an nur der Konstruktor aufgerufen wird.

    Nexus schrieb:

    Zumindest dachte ich, es wäre nicht erlaubt, dass die Optimierung das Programmverhalten ändert...

    In diesem Fall ist es erlaubt, genauso wie bei der vielgerühmten "return value optimization", wo ja auch der Copy-Konstruktor umgangen wird.

    Dennoch, obwohl unter Strich (meist) dasselbe herauskommt ist die Version

    Device d2("Device 2");
    

    die empfohlene Variante, daher war dein Tipp meiner Meinung nach grundsätzlich berechtigt



  • Hmm. Merkwürdige Sache. Der Kopierkonstruktor scheint tatsächlich nicht aufgerufen zu werden, ich hab nochmal geschaut...

    Vor allem ist die Direktinitialisierung die einzige Möglichkeit, wenn man zum Beispiel nicht-kopierbare Objekte hat.



  • Nexus schrieb:

    Hmm. Merkwürdige Sache.

    Wieso ist das merkwürdig? Wir hatten uns doch geeinigt :), dass das Ding wegoptimiert wird.

    Dass er aber grundsätzlich gebraucht wird, also tatsächlich erst durch Optimierung wegfällt zeigt die private-Version. Oder verstehe ich dich jetzt falsch?



  • Kritiker schrieb:

    Dennoch, obwohl unter Strich (meist) dasselbe herauskommt ist die Version

    Device d2("Device 2");
    

    die empfohlene Variante, daher war dein Tipp meiner Meinung nach grundsätzlich berechtigt

    Dann müsstest du aber auch:

    int i (2);
    

    machen. 😉

    Ich Ich finds in manchen Situationen einfach lesbarer und schneller verständlich, wenn ich das mit dem Zuweisungsoperator (welcher hier keiner ist ) zu schreiben.

    Klar, wenn man einen Konstruktor verschieden vom Kopierkonstruktor hat, dann hat man in diesem Falle ein Problem..



  • Es geht bei der Empfehlung natürlich um die Initialisierung mit Konstruktoraufruf. Bei int usw. gibt es die Unterschiede ja nicht.

    Was jetzt übersichtlicher ist liegt selbstverständlich im Auge des Betrachters, da will ich keine Wertung abgeben.

    Aber, klar ist auch, dass die Variante

    int i (2);
    Device d2("Device 2");
    // ... usw. usw.
    

    immer funktioniert, während man mit

    int i = 2;
    Device d2 = Device("Device 2");
    Device d2 = "Device 2";
    // ... usw. usw.
    

    durchaus straucheln kann und gezwungen ist die erstgenannte Variante zu wählen, auch wenn man sie als unübersichtlich empfindet.

    Nun gut, das sind ja alles mehr oder weniger unwichtige Details, soll jeder machen wie es ihm beliebt .... 😃



  • Kritiker schrieb:

    immer funktioniert, während man mit

    Wirklich immer? 🙂

    foo g = foo ( foo ( foo () ) );
    //vs
    foo f ( foo( foo ( foo () ) ) );
    

    Über Sinn und Unsinn von solchen Konstrukten sei wo anders diskutiert..



  • drakon schrieb:

    Wirklich immer? 🙂

    Die Entsprechung zu

    foo g = foo ( foo ( foo () ) );
    

    ist nicht die Funktionsdeklaration

    foo f ( foo( foo ( foo () ) ) );
    

    sondern der Aufruf des Standardkonstruktors

    foo f;
    

    Du könntest jetzt anführen, dass der Copy-Konstruktor wichtige Änderungen am Objekt vornimmt und deshalb genau 3-mal hintereinander aufgerufen werden muss.

    Dem halte ich entgegen, dass du

    1. den mehrfachen Aufruf nicht garantieren kannst (Wenn doch, will ich wissen wie du es gemacht hast!!!) und

    2. wäre ja dann auch nicht garantiert, dass

    foo g = foo();
    foo g;
    

    oder

    foo dummy;
    foo g = dummy;
    foo g(dummy);
    

    jeweils dasselbe Ergebnis für g liefert.

    Du hättest sozusagen ernsthafte Problem zu erklären warum

    foo g = foo ( foo ( foo () ) );
    

    nicht gleichbedeutend ist mit

    foo f;
    

    Aber klar, da ich "immer" gesagt habe, hast du meine Aussage sozusagen mit einem chaotischen Copy-Konstruktor "logisch" widerlegt.

    Genieße die Genugtuung! 😃 😃 😃


Anmelden zum Antworten