Smart Pointer
-
Reicht's fürs Multithreading nicht, den gesamten Baum zu locken, solange er geschrieben wird? Ich würd's mir nicht so kompliziert machen. Gerade wenn die Lesevorgänge fürs UI sind, muss das ja nicht so schnell sein.
-
Hi, ich habe jetzt mal Testweise in meinem Programm die rohen Zeiger angefangen durch SmartPointer zu ersetzen. Leider macht das ein paar Probleme.
Wie umgehe ich z.B. folgendes Problem, das mit normalen Zeigern funktioniert:std::shared_ptr<Base> Test(std::shared_ptr<Base> test) { std::shared_ptr<Derived> ptr(test); ptr->DerivedSpecificFunction(); return ptr; // Geht nicht, da kein passenender Konstruktor für die Konvertierung von Derived in Base vorhanden. }Und was mache ich wenn verschiedene Zeiger Typen aufeinander stoßen, ich also z.B. einen std::vector<std::shared_ptr<Object>> habe der nun aber auch einen Zeiger auf ein Objekt aufnehmen soll, das von einem std::unique_ptr<Object> verwaltet wird?
-
Sorry, im Beispiel oben fehlt noch ein dynamic_pointer_cast, aber so gehts auch nicht:
std::shared_ptr<Base> Test() { std::shared_ptr<Derived> ptr(new Derived()); ptr->DerivedSpecificFunction(); return ptr; // Geht nicht, da kein passenender Konstruktor für die Konvertierung von Derived in Base vorhanden. }
-
Du sollst doch nicht alle rohen Zeiger durch Smart-Pointer ersetzen! Nur die besitzenden, sprich die, die in irgendeiner Weise bspw. den Speicherplatz des Pointees verwalten!
Edit: Ich sehe, das zweite Beispiel ist schon passender.
-
Merkwürdig, das sollte automatisch gehen. Compiler (+Version)?
-
Hier macht shared_ptr gar keinen Sinn. Abgesehen davon, dass sich dein Problem auch mit shared_ptr lösen lässt, so macht man das richtig:
std::unique_ptr<Base> Test() { Derived *d = new Derived; unique_ptr<Base> b(d); d->DerivedSpecificFunction(); return b; }
-
Benutze Visual Studio 2012. Das würde ich ja gerne tun, aber wenn der Owner meiner Objekte eindeutig wäre bräuchte ich gar keine SmartPointer, dann würde ich die Objekte einfach im Destructor deleten und fertig. Leider ist die Praxis eine andere. Stellt euch vor ich habe Resourcen die am Programmstart geladen und ganz am Schluss wieder freigegeben werden. Diese würde man z.B. mit einem unique_ptr verwalten, da hier der Owner klar ist. Oder besser ganz ohne SmartPointer. Eine solche Resource könnte ein Style sein. Dieser wird nun dem Style-Property-Zeiger eines Controls zugewiesen. Aber der User kann darüber hinaus auch selber einen Style dynamisch erzeugen und diesem Style-Property zuweisen. Woher soll das Style-Property nun aber wissen ob dieser Style womöglich eine Resource ist und später automatisch gelöscht wird oder ob sich das Control selber darum kümmern muss?
Mal ein wenig Pseudocode ohne SmartPointer, dann wirds vielleicht versändlicher:
Style* GetDefaultStyleFromResourceManager(Type type) { ... return style; } class Control { public: Control(); void SetStyle(Style* style); private: Style* style; }; Control::Control() { style = GetDefaultStyleFromResourceManager(...); } void Control::SetStyle(Style* style) { this->style = style; } int main() { Style* myCustomStyle = new Style(); myCustomStyle->Background(255, 255, 0, 0); Control* myControl = new Control(); myControl->SetStyle(myCustomStyle); return 0 }Wie Sorge ich nun dafür, dass der myCustomStyle gelöscht wird?
Und bitte empfehlt mir jetzt nicht diesen am Ende der main-Funktion zu löschen, das ist jetzt nur ein vereinfachtes Beispiel.
-
Oder noch ein schönes Beispiel:
Control::GetTransform() { TransformGroup* group = new TransformGroup(); const Vector& offset = GetOffset(); group->Add(new TranslateTransform(offset.X(), offset.Y())); const Vector& scale = GetScale(); group->Add(new ScaleTransform(scale.X(), scale.Y())); return group; }void Control::ApplyTransforms() { Object* obj = this; TransformGroup* group = new TransformGroup(); while (obj) { group->Add(obj->GetTransform()); obj = obj->Parent(); } ... }Jetzt werdet ihr euch wahrscheinlich fragen warum ich diese Transformationen überhaupt dynamisch erzeuge. Ganz einfach. Das liegt an meinem Propertysystem und daran, dass natürlich auch Transformationen Ressourcen sein können. Man kann z.B. für jeden Control-Type eine Default-Transformation im ResourcenManager abrufen, aber auch Benutzerdefinierte-Transformationen zuweisen.
-
Aber genau dafür sind SmartPointer doch da o.O Damit musst du dir über das deleten keine größeren Gedanken machen.
-
Wie Sorge ich nun dafür, dass der myCustomStyle gelöscht wird?
Indem du unique_ptr nutzt. Einfach:
private: std::unique_ptr<Style> style; };Und wenn der Style eine gemeinsame Ressource ist, dann eben shared_ptr.