vector hinzufügen ohne objekt zu kopieren (ggf. refcount++)



  • ich lasse jetzt die Berechnungen das übergeordnete TElement machen und kann somit auf die Pointer verzichten. Ich denke das ist die sinnvollste und stabilste Variante.

    Danke trotzdem an alle, die mitgeholfen haben



  • mhm, klappt doch nicht ganz ohne die pointer,

    probiere schon eine Weile rum, aber komme nicht wirklich weiter mit dem unique_ptr...

    typedef std::vector<std::unique_ptr<TElement>> pElementList;
    pElementList pElements;
    
    unique_ptr<TElement> pE(new TElement());
    pE->InitElement(this,Template,left,top,4,4);
    pElements.push_back(pE);
    

    bei der letzten Zeile wirft mir der cimpiler eine 10-seitige Fehlermeldung um die Ohren aus der ich nicht wirklich was herausnehmen kann...

    In file included from /usr/include/c++/4.4/i486-linux-gnu/bits/c++allocator.h:34,
    from /usr/include/c++/4.4/bits/allocator.h:48,
    from /usr/include/c++/4.4/string:43,
    from /usr/include/c++/4.4/bits/locale_classes.h:42,
    from /usr/include/c++/4.4/bits/ios_base.h:43,
    from /usr/include/c++/4.4/ios:43,
    from /usr/include/c++/4.4/ostream:40,
    from /usr/include/c++/4.4/iostream:40,
    from platine.h:1,
    from platine.cpp:1:
    /usr/include/c++/4.4/bits/unique_ptr.h: In member function ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = std::unique_ptr<TElement, std::default_delete<TElement> >]’:
    /usr/include/c++/4.4/bits/stl_vector.h:737: instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = std::unique_ptr<TElement, std::default_delete<TElement> >, _Alloc = std::allocator<std::unique_ptr<TElement, std::default_delete<TElement> > >]’
    platine.cpp:499: instantiated from here
    /usr/include/c++/4.4/bits/unique_ptr.h:214: error: deleted function ‘std::unique_ptr<_Tp, _Tp_Deleter>::unique_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = TElement, _Tp_Deleter = std::default_delete<TElement>]’
    /usr/include/c++/4.4/ext/new_allocator.h:105: error: used here
    In file included from /usr/include/c++/4.4/vector:69,
    from platine.h:3,
    from platine.cpp:1:
    /usr/include/c++/4.4/bits/unique_ptr.h: In member function ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, _Args&& ...) [with _Args = const std::unique_ptr<TElement, std::default_delete<TElement> >&, _Tp = std::unique_ptr<TElement, std::default_delete<TElement> >, _Alloc = std::allocator<std::unique_ptr<TElement, std::default_delete<TElement> > >]’:
    /usr/include/c++/4.4/bits/stl_vector.h:741: instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = std::unique_ptr<TElement, std::default_delete<TElement> >, _Alloc = std::allocator<std::unique_ptr<TElement, std::default_delete<TElement> > >]’
    platine.cpp:499: instantiated from here
    /usr/include/c++/4.4/bits/unique_ptr.h:214: error: deleted function ‘std::unique_ptr<_Tp, _Tp_Deleter>::unique_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = TElement, _Tp_Deleter = std::default_delete<TElement>]’
    /usr/include/c++/4.4/bits/vector.tcc:314: error: used here



  • Es muss

    pElements.push_back(std::move(pE));
    

    heißen. Dies hat auch Nexus falsch gemacht.



  • ok, danke

    kann ich da nicht auf unique_ptr verzichten und std::move beim normalen vector anwenden (damit keine Kopie erstellt wird)?

    TElement e;
    fElements.push_back(std::move(e));
    

    der compiler frisst es zumindest 😉



  • Wenn der Default-Move-Ctor das richtige tut, oder du deinen eigenen hast, schon.



  • Was du auch noch machen könntest, wäre emplace_back zu verwenden. Dem übergibt man die Konstruktor-Argumente und das Element wird ohne Kopie direkt im vector erstellt.



  • 314159265358979 schrieb:

    Wenn der Default-Move-Ctor das richtige tut, oder du deinen eigenen hast, schon.

    ich habe einen leeren constructor, da ich die Klasse erst mit der InitElement initialisiere...
    ich weis ja nicht, ob std::move das tut, was ich will...er soll das erstellte objekt in den Vector "moven" (also nicht kopieren, sondern verschieben)



  • Ein neues Objekt muss bei push_back auf jeden Fall erstellt werden. Das mit InitElement vergiss mal wieder, das ist Schwachsinn. Member werden im Ctor initialisiert. Ich würde wohl die Variante mit unique_ptr nehmen.



  • mhm...
    muss ich auf noch irgendwas achten, oder kann ich das einfach so verwenden:

    typedef std::vector<std::unique_ptr<TElement>> pElementList;
      pElementList pElements;
    
      unique_ptr<TElement> pE(new TElement());
      pE->InitElement(this,Template,left,top,4,4);//init-code in constructor verlagern
      pElements.push_back(std::move(pE));
    

    stimmt der zugriff? freigegeben wird das TElement ja, wenn die liste zerstört wird, oder? bzw. wenn ich erase aufrufe...kann ich irgendwie elemente ohne iterator löschen? also per index-zugriff (z.b. remove(4) soll das 5.element löschen)?



  • Stimmt so, ja. Ein Element an einer bestimmten Position im vector kannst du löschen durch:

    vec.erase(vec.begin() + n);
    

    Bei vector könnte sowas jedoch langsam sein, da hier alle Elemente hinter dem gelöschten um eine Stelle vorgeschoben werden müssen.



  • 314159265358979 schrieb:

    Bei vector könnte sowas jedoch langsam sein, da hier alle Elemente hinter dem gelöschten um eine Stelle vorgeschoben werden müssen.

    welche Alternativen gäbe es denn? prinzipiell brauche ich ja ein dynamisches array mit Klassen-Elementen.



  • frank schrieb:

    314159265358979 schrieb:

    Bei vector könnte sowas jedoch langsam sein, da hier alle Elemente hinter dem gelöschten um eine Stelle vorgeschoben werden müssen.

    welche Alternativen gäbe es denn? prinzipiell brauche ich ja ein dynamisches array mit Klassen-Elementen.

    Wenn die Reihenfolge im Vektor egal ist, such mal das erase-remove Idiom.



  • nach bisschen suchen zu dem erase/remove kam mir die idee, ich könnte das zu löschende item mit dem letzten tauschen und dann den vector 1 kleiner machen bzw. dann löschen...dann umgehe ich das nachrutschen. da ich die einzelnen Elemente eh per pointer referenziere oder die liste von vorne nach hinten durchgehe (wo mit die reihenfolge egal ist) wäre das eigentlich egal, an welcher stelle ein bestimmtes item ist.

    nur wie tausche ich am elegantesten 2 Items in einem Vector?



  • Guck dir mal std::remove() an.



  • std::remove erwartet eine value (ein int-wert, string,...). kann ich da auch meine unique_ptr entfernen, ohne dass speicherlecks (vom TElement) zurückbleiben?

    wie würde das aussehen?

    ich würde vermuten so in etwa:

    pElements.erase(std::remove(pElements.begin(), pElements.end(), pElements[index]), pElements.end());
    


  • frank schrieb:

    nach bisschen suchen zu dem erase/remove kam mir die idee, ich könnte das zu löschende item mit dem letzten tauschen und dann den vector 1 kleiner machen bzw. dann löschen...dann umgehe ich das nachrutschen. da ich die einzelnen Elemente eh per pointer referenziere oder die liste von vorne nach hinten durchgehe (wo mit die reihenfolge egal ist) wäre das eigentlich egal, an welcher stelle ein bestimmtes item ist.

    nur wie tausche ich am elegantesten 2 Items in einem Vector?

    So wäre es gut:

    template<typename T>
    void delete_element(std::vector<T>& vec, std::size_t index)
    {
      std::swap(vec.at(index), vec.back());
      vec.resize(vec.size() - 1);
    }
    


  • Hallo,
    nachdem der unique_ptr für TElement super funktioniert, wollte ich das ganze auch für die unterklasse TConnection machen...

    kann mir mal jemand verraten, wie man aus diesem Kauderwelsch etwas entnehmen kann?

    $ g++ -Wall -std=c++0x platine.cpp -o platine `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0`
    In file included from /usr/include/c++/4.4/vector:64,
                     from platine.h:3,
                     from platine.cpp:13:
    /usr/include/c++/4.4/bits/unique_ptr.h: In static member function ‘static _ForwardIterator std::__uninitialized_copy<<anonymous> >::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<TConnection, std::default_delete<TConnection> >*, std::vector<std::unique_ptr<TConnection, std::default_delete<TConnection> >, std::allocator<std::unique_ptr<TConnection, std::default_delete<TConnection> > > > >, _ForwardIterator = std::unique_ptr<TConnection, std::default_delete<TConnection> >*, bool <anonymous> = false]’:
    /usr/include/c++/4.4/bits/stl_uninitialized.h:117:   instantiated from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<TConnection, std::default_delete<TConnection> >*, std::vector<std::unique_ptr<TConnection, std::default_delete<TConnection> >, std::allocator<std::unique_ptr<TConnection, std::default_delete<TConnection> > > > >, _ForwardIterator = std::unique_ptr<TConnection, std::default_delete<TConnection> >*]’
    /usr/include/c++/4.4/bits/stl_uninitialized.h:257:   instantiated from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<TConnection, std::default_delete<TConnection> >*, std::vector<std::unique_ptr<TConnection, std::default_delete<TConnection> >, std::allocator<std::unique_ptr<TConnection, std::default_delete<TConnection> > > > >, _ForwardIterator = std::unique_ptr<TConnection, std::default_delete<TConnection> >*, _Tp = std::unique_ptr<TConnection, std::default_delete<TConnection> >]’
    /usr/include/c++/4.4/bits/stl_vector.h:243:   instantiated from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = std::unique_ptr<TConnection, std::default_delete<TConnection> >, _Alloc = std::allocator<std::unique_ptr<TConnection, std::default_delete<TConnection> > >]’
    platine.h:199:   instantiated from here
    /usr/include/c++/4.4/bits/unique_ptr.h:214: error: deleted function ‘std::unique_ptr<_Tp, _Tp_Deleter>::unique_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = TConnection, _Tp_Deleter = std::default_delete<TConnection>]’
    /usr/include/c++/4.4/bits/stl_uninitialized.h:74: error: used here
    
    class TConnection
    
    {
      ...
      public:
    
        TConnection(TPlatine *board,TElement *elmt,int ID,string name); //inside TElement
        //TConnection(TPlatine *board,int x,int y,string name); //outside TElement
    
        virtual ~TConnection() {};
    ...
    }
    
    typedef std::vector<std::unique_ptr<TConnection>> pConnectionList;
    
    class TElement
    
    {
    ...
      public:
    
    ...
        pConnectionList pConnections;
    

    der Fehler kommt erst wenn ich das pConnections-Feld in TElement einbaue. bei der reinen typedef nicht. Dachte erst, es liegt an meinen 2 Ctoren, aber der Fehler kommt auch nur mit einem...
    ich habe im code noch nichts, wo ich auf pConnections zugreife (bzw. auskommentiert).



  • Dasselbe wie vorhin, du versuchst irgendwo einen unique_ptr zu kopieren.



  • eben nicht, wenn ich die Zeile im TElement auskommentiere wird fehlerfrei compiliert...ich verwende also nirgendwo das pConnections. somit wird davon auch kein Element kopiert

    die ganzen Zugriffe habe ich schon auskommentiert zur Fehlereingrenzung



  • platine.h Zeile 199.


Anmelden zum Antworten