Vector leeren



  • 314159265358979 schrieb:

    In den meisten fällen reicht ein unique_ptr vollkommen aus, und den gibts in boost und C++0x.

    boost::interprocess::unique_ptr ist ohne Rvalue-Referenzen (C++0x Feature) und ohne STL-Unterstützung von move-only Typen (C++0x Feature) nur eingeschränkt brauchbar. Das letzte mal, als ich libstdc++ bzgl unique_ptr-Implementierung getestet hatte, funktionierte map<string,unique_ptr<int> > noch nicht richtig, weil es da irgendwelche Probleme mit std::pair und Move-Konstruktoren gab.

    Statt vector<unique_ptr<T> > kann man auch boost::ptr_vector<T> verwenden. Das funktioniert dann auch ohne C++0x Features.



  • Xenya schrieb:

    wegen dem, dass ich das new weglassen soll.
    Ich bin in C++ nicht wirklich erfahren, deshalb könnte das nun ziemlich falsch sein:
    Wenn ich es auf dem Stack anlege verliert es doch nach dem Scope seine Gültigkeit. Deshalb dachte ich, wenn ich ohne new das Element dem Vektor hinzufüge, ist es außerhalb der Methode nicht mehr vorhanden.

    Ja das ist falsch. Beim Hinzufügen in den vector wird nicht das Objekt selbst hinzugefügt, sondern eine Kopie erzeugt. Das Objekt wird am Ende der Methode zerstört, aber die Kopie lebt weiter, um deren Lebenszeit kümmert sich der vector.
    Dabei ist es übrigens egal, ob der vector Zeigertypen enthält. Dann werden eben Kopien der Zeiger angelegt (aber eben nicht der gezeigten Objekte).

    Also: ja, lass das new weg.



  • 314159265358979 schrieb:

    Warum wird hier eigentlich überall auf shared_ptr verwiesen? In den meisten fällen reicht ein unique_ptr vollkommen aus, und den gibts in boost und C++0x.

    Weil einige leider nicht den Luxus haben, boost und/oder C++0x zur Verfügung zu haben! 😞



  • HighLigerBiMBam schrieb:

    Sofern dein Compiler schon C++0x features unterstützt gibt es dort den std::tr1::shared_ptr<>

    Der Post war es, der mich besonders gestört hat. Denn wer C++0x hat, der hat auch nen unique_ptr.



  • 314159265358979 schrieb:

    HighLigerBiMBam schrieb:

    Sofern dein Compiler schon C++0x features unterstützt gibt es dort den std::tr1::shared_ptr<>

    Der Post war es, der mich besonders gestört hat. Denn wer C++0x hat, der hat auch nen unique_ptr.

    Abgesehen davon: Was hat denn der shared_ptr aus dem bereits existierenden TR1 mit dem zukünftigen Standard C++0x zu tun? Oder ist der TR1 kein "echter" Bestandteil des aktuellen C++-Standards?



  • TR1 ist eben Technical Report 1. Das ist der wahrscheinlich-bald-Standard, aber solange nix abgesegnet ist, kann der noch geändert werden.



  • Oh. 😮

    Theoretisch könnten dann beim nächsten C++-Standard TR1-Bestandteile geändert werden und bisheriger Code, der TR1-Futures benutzt, könnte dann nicht mehr standardkonform sein?

    Ich dachte (das ist der Fehler! ;)), dass die TR1-Inhalte quasi feste Bestandteile des folgenden Standards sind. Nach dem Motto: "Das ist garantiert im nächsten Standard dabei!"



  • Roger Wilco schrieb:

    Ich dachte (das ist der Fehler! ;)), dass die TR1-Inhalte quasi feste Bestandteile des folgenden Standards sind. Nach dem Motto: "Das ist garantiert im nächsten Standard dabei!"

    Es ist nicht garantiert dabei, aber große Teile werden übernommen, ggf. mit leichte Modifikationen, die die neuen Möglichkeiten von C++0x berücksichtigen. Danach sind 4 verschiedene Dinge zu unterscheiden:

    - Die Spezifikationen im TR1
    - Die TR1-Implementierung durch die Compilerhersteller
    - Die Spezifikation im 0x-Standard
    - Die 0x-Implementierung durch die Compilerhersteller

    Alle zusammen müssen nicht identisch sein, sollten aber nur geringe Abweichungen voneinander haben.



  • vielen lieben Dank, dass ihr euch Zeit genommen und mir nicht nur eine Lösung gezeigt, sondern auch einiges erklärt habt.

    Wenn ich es also den Vector ohne new befülle, reicht es um die Member-Variable wieder zu leeren, in dem ich nur die Swap Methode aufrufe?

    Und nen Destruktor brauche ich dafür dann auch nicht mehr, da der komplette Speicher selbst freigegeben wird, wenn das Klassen-Objekt das diese Membervariable hat, zerstört wird.



  • Swap? theVector.clear() reicht.

    Edit: Wobei std::vector().swap(vec); auch interessant aussieht, aber welche Vorteile hat das?





  • swap() zum Leeren würde ich allerdings nur einsetzen, wenn es relevante Vorteile bringt. Es hat schon seine Gründe, warum clear() den Speicher nicht freigibt.



  • Würde nicht clear() gefolgt von resize(0) auch reichen? Als Grund stattdessen swapp/erase zu nutzen würde mir höchstens einfallen das andere STL Container kein resize() bieten und das somit für refaktoring günstiger wäre? Mhh vektor, list, deque bieten resize an, map, multimap und queue nicht - dafür habe map und multimap eigene swap Implementationen 😕

    Edith: Ok, swap with temporary reduziert den Speicher auf 0, clear/resize löscht alles, gibt aber keien reservierten Speicher frei 🙂



  • Würde nicht clear() gefolgt von resize(0)

    Nein. Das ist nicht dasselble wie swap with a temporary.



  • Resultat nachdem man mich mit der Nase reinstieß: swap mit temporary != clear();resize(); da letzteres keinen reservierten Speicher freigibt.

    class Elem
    {
        static int count_default;
        static int count_copy;
        static int count_opEqual;
        static int count_destruct;
    
    public:
        Elem()                           { ++count_default;  }
        Elem(const Elem & e)             { ++count_copy;     }
        Elem & operator=(const Elem & o) { ++count_opEqual;  return *this; }
        ~Elem()                          { ++count_destruct; }
    
        static void output()
        {
            std::cout << "DefaConst\tCopyConst\toperEqual\tDestructor\n" << count_default << "\t" << count_copy << "\t"<< count_opEqual << "\t"<< count_destruct << "\n\n\n" << std::endl;
            count_default=0;
            count_copy=0;
            count_opEqual=0;
            count_destruct=0;
        }
    };
    
    int Elem::count_default(0);
    int Elem::count_copy(0);
    int Elem::count_opEqual(0);
    int Elem::count_destruct(0);
    
    int main()
    {
        std::cout << "just out of scope:\n";
        {
            std::vector<Elem> es;
            // es.reserve(100); // 2. Ausgabe
            for (int i=0; i< 100; ++i) es.push_back(Elem());
        }
        Elem::output();
    
        std::cout << "clear and resize:\n";
        {
            std::vector<Elem> es;
            es.reserve(100);
            for (int i=0; i< 100; ++i) es.push_back(Elem());
    
            int cap_before = es.capacity();
            es.clear();
            es.resize(0);
            std::cout << "Capacity before/after: " << cap_before << "/" << es.capacity()<< std::endl;
        }
        Elem::output();
    
        std::cout << "swap with temoprary:\n";
        {
            std::vector<Elem> es;
            es.reserve(100);
            for (int i=0; i< 100; ++i) es.push_back(Elem());
    
            std::cout << es.capacity()<< std::endl;
            int cap_before = es.capacity();
            std::vector<Elem>().swap(es);
            std::cout << "Capacity before/after: " << cap_before << "/" << es.capacity()<< std::endl;
        }
        Elem::output();
    
    }
    
    CopyConst und Destructor: ohne/mit es.reserve(100);
    
    just out of scope:
    DefaConst    CopyConst    operEqual    Destructor
    100          227/100          0            327/200
    
    clear and resize:
    Capacity before/after: 100/100
    DefaConst    CopyConst    operEqual    Destructor
    101          227/100          0            328/201
    
    swap with temoprary:
    Capacity before/after: 100/0
    DefaConst    CopyConst    operEqual    Destructor
    100          227/100          0            327/200
    


  • padreigh schrieb:

    Würde nicht clear() gefolgt von resize(0) auch reichen?

    Das resize bringt da gar nichts. resize legt nur die Anzahl der Elemente fest, der reservierte Speicher wird aber nur verändert, wenn er vergößert werden muss.



  • ipsec schrieb:

    padreigh schrieb:

    Würde nicht clear() gefolgt von resize(0) auch reichen?

    Das resize bringt da gar nichts. resize legt nur die Anzahl der Elemente fest, der reservierte Speicher wird aber nur verändert, wenn er vergößert werden muss.

    Stimmt - ich habe die API wohl fehlinterpretiert:

    http://www.cplusplus.com/reference/stl/vector/resize/

    Change size
    Resizes the vector to contain sz elements. If sz is smaller than the current vector size, the content is reduced to its first sz elements, the rest being dropped.

    "the rest being dropped." beschränkt also nicht die Kapazität sondern nur den aktuellen Inhalt. Danke 🙂 wieder was gelernt.


Anmelden zum Antworten