Shared Pointer -> Typ ändern
-
Hi zusammen,
kann man irgendwie in einem fertigen Shared Pointer Vector nachträglich von einigen Elementen den Typ ändern?
Was ich will, ist das, was in tuwas passiert.
#include <iostream> #include <vector> #include <memory> #include <string> #include <sstream> struct base { int a; explicit base(int a = 0) : a(a) {} virtual std::string str() const { std::ostringstream mybuf; mybuf << "i'm a base(" << this->a << ")\n"; return mybuf.str(); } }; struct derived : base { int b; explicit derived(int a = 0, int b = 0) : base(a), b(b) {} virtual std::string str() const { std::ostringstream mybuf; mybuf << "i'm derived(" << this->a << ", " << this->b << ")\n"; return mybuf.str();} }; typedef std::vector<std::shared_ptr<base>> container_type; void add_base(container_type& vec) { vec.push_back(typename container_type::value_type(new base(1))); } void add_derived(container_type& vec) { vec.push_back(typename container_type::value_type(new derived(2, 3))); } void tuwas(container_type& vec) { *(vec[1])=base(7); // shared-Pointer Typ soll sich ändern. Vorher: derived. Jetzt: base! } int main() { container_type myvec; add_base(myvec); add_derived(myvec); add_derived(myvec); std::cout << "there are " << myvec.size() << " entries, they're:\n"; for (unsigned i=0; i<myvec.size();i++) std::cout << myvec->str(); tuwas(myvec); std::cout << "---\n"; for (unsigned i=0; i<myvec.size();i++) std::cout << myvec[i]->str(); }
Die erste Anzeige ist:
`basederived
derived
Und sollte nach tuwas() zu
basebase
derived`
werden. Der zweite Eintrag bleibt aber vom Typ derived ...[i]Der Basisquellcode stammt von asdfasd als Antwort auf eine Frage. Danke asdfasfd!*
Vielen Dank im Voraus!
-
Was du machst, ist Slicing. Nicht gut!
Nutze
shared_ptr::reset()
oder gleichshared_ptr::operator=
undmake_shared()
.
-
Ersetze shared_ptr mit unique_ptr. Dein Code geht danach genauso, ist aber schneller und designtechnisch korrekter.
-
Nexus schrieb:
Nutze
shared_ptr::reset()
Super! Das geht schonmal!
Alles weitere ist schönes Bonuswissen für mich:
(ich mag das!)
oder gleich
shared_ptr::operator=
undmake_shared()
.hmm damit komm ich nicht klar. Ich habs jetzt zwar auf S.992 von Stroustrup gefunden. Aber warum gerade make_shared() und wie soll das jetzt aussehen?
Und warum ist das besser als das Obige?unique_ptr ftw schrieb:
Ersetze shared_ptr mit unique_ptr. Dein Code geht danach genauso, ist aber schneller und designtechnisch korrekter.
Warum soll unique_ptr hier designtechnisch korrekter sein?
"shared_ptr to represent shared ownership" Stroustrup S.112
Offensichtlich wird es doch von base und derived geshared?Vielen Dank euch beiden!
-
Lymogry schrieb:
oder gleich
shared_ptr::operator=
undmake_shared()
.hmm damit komm ich nicht klar. Ich habs jetzt zwar auf S.992 von Stroustrup gefunden. Aber warum gerade make_shared() und wie soll das jetzt aussehen?
Und warum ist das besser als das Obige?void tuwas(container_type& vec) { vec[1] = std::make_shared<base>(7); }
Ist intuitiver als reset und außerdem wird dabei Referenzzähler und Objekt in einem Block alloziiert.
Lymogry schrieb:
Warum soll unique_ptr hier designtechnisch korrekter sein?
"shared_ptr to represent shared ownership" Stroustrup S.112
Offensichtlich wird es doch von base und derived geshared?Es gibt nur einen Besitzer und das ist der Vector myvec, also gibt es (noch) keine shared ownership.
-
Lymogry schrieb:
oder gleich
shared_ptr::operator=
undmake_shared()
.hmm damit komm ich nicht klar. Ich habs jetzt zwar auf S.992 von Stroustrup gefunden. Aber warum gerade make_shared() und wie soll das jetzt aussehen?
Und warum ist das besser als das Obige?operator= : vec[1] = new base(7)
make_shared: shared_ptr<T>(new T(foo)) wird zu make_shared<T>(foo). Gewöhn dir das an, ist effizienter und bei manchen Dingen, die einzige Möglichkeit Leaks zu vermeiden.unique_ptr ftw schrieb:
Ersetze shared_ptr mit unique_ptr. Dein Code geht danach genauso, ist aber schneller und designtechnisch korrekter.
Warum soll unique_ptr hier designtechnisch korrekter sein?
"shared_ptr to represent shared ownership" Stroustrup S.112
Offensichtlich wird es doch von base und derived geshared?Nee.
shared ownership heißt, dass vector a und vector b sich den Besitz über die base/derived Objekte teilen. Das ist hier nicht der Fall, da du nur einen Besitzer hast.
Verwende deshalb per default unique_ptr, den kann man zwar nicht kopieren, aber wenn man das braucht kann man immer noch zum shared_ptr wechseln (Wenn mans braucht! Meistens braucht man das nicht.).
-
Nathan schrieb:
Lymogry schrieb:
oder gleich
shared_ptr::operator=
undmake_shared()
.hmm damit komm ich nicht klar. Ich habs jetzt zwar auf S.992 von Stroustrup gefunden. Aber warum gerade make_shared() und wie soll das jetzt aussehen?
Und warum ist das besser als das Obige?operator= : vec[1] = new base(7)
Geht nicht. Der
shared_ptr
ctor der nen rohenT*
nimmt ist explicit. Und das ist gut so!
Würde sonst ganz schnell zu double-deletes führen.Was geht ist
vec[1] = shared_ptr<base>(new base(7));
Oder eben bleich eine der hübscheren Varianten (reset()
,make_shared()
).
-
hustbaer schrieb:
Nathan schrieb:
Lymogry schrieb:
oder gleich
shared_ptr::operator=
undmake_shared()
.hmm damit komm ich nicht klar. Ich habs jetzt zwar auf S.992 von Stroustrup gefunden. Aber warum gerade make_shared() und wie soll das jetzt aussehen?
Und warum ist das besser als das Obige?operator= : vec[1] = new base(7)
Geht nicht. Der
shared_ptr
ctor der nen rohenT*
nimmt ist explicit. Und das ist gut so!
Würde sonst ganz schnell zu double-deletes führen.Was geht ist
vec[1] = shared_ptr<base>(new base(7));
Oder eben bleich eine der hübscheren Varianten (reset()
,make_shared()
).Oh, stimmt. Hab ich vergessen.
-
VIELEN DANK!
-
ich kann mich auch irren aber ich glaube mich zu erinnern, dass als ich das letzte mal effective c++ gelesen habe, der autor ausdrücklich gemeint hat, dass vectoren nur typen akzeptieren die intuitiv copy-ctor'bar sind (was bei shared_ptr der fall ist, nicht aber bei unique_ptr).
bitte berichtigt mich, ich hab mir den kram mit den move-semantics in c++11 noch nicht angeschaut, vll liege ich daher falsch.
-
Du kannst move-only-Typen wie unique_ptr in Container tun, ohne Probleme.
-
asdfasfd schrieb:
ich kann mich auch irren aber ich glaube mich zu erinnern, dass als ich das letzte mal effective c++ gelesen habe, der autor ausdrücklich gemeint hat, dass vectoren nur typen akzeptieren die intuitiv copy-ctor'bar sind (was bei shared_ptr der fall ist, nicht aber bei unique_ptr).
bitte berichtigt mich, ich hab mir den kram mit den move-semantics in c++11 noch nicht angeschaut, vll liege ich daher falsch.Hi
Ich hab mir diesen Thread nun nach einer Woche noch mal angesehen und auch unique-ptr und shared_ptr nochmal genauer angeguckt.
S. 470 C++ Primer (engl 5. Edition)
steht ausdrücklich, dass hier:uqique_ptr<string> p1(new string("Stego")); unique_ptr<string>p2(p1); // ERROR no copy for unique_ptr unique_ptr<string>p3; p3=p2; // ERROR no assign for unique_ptr
Und genau diesen assign Operator brauche ich doch und nehme deswegen
vec[1] = std::make_shared<base>(7);
Liege ich damit nun richtig?
-
Steht da kein Satz zu Move-Operatoren und Move-Konstrukoren, wenn sie schon mit unique_ptr anfangen?