vector hinzufügen ohne objekt zu kopieren (ggf. refcount++)
-
über gebe ich dann die Speicheradresse??
also push_back(&c)?
ggf. mit cast auf unique pointer oder wie läuft das dann?
wie bekomme ich mein Objekt wieder raus und wie ist das mit der Speicherfreigabe?
-
Du musst die Objekte dynamisch anlegen. Freigegeben werden sie automatisch, da es sich um einen Smart-Pointer handelt.
std::unique_ptr<TConnection> c(new TConnection(fPlatine,this,id,s)); Connections.push_back(c);
-
mhm, kann ich da einfach per list[i] auf die TConnections zugreifen?
habe überlegt, obs nicht sinnvoller wäre die ganze pointer-verarbeitung aus dem constructor rauszuverlagern (init-prozedure), die ich auf das listen-element ausführe.
Pseudocode:
std::vector<TConnection> TConnectionList; TConnectionList clist; TConnection c(); clist.push_back(c); clist[clist.size()-1].init(...)
-
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 hereclass 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).