Polymorpher Smartpointer
-
Moin,
Manchmal denke ich mir, dass ich eine Art Polymorphen Smartpointer brauche. Also ein Smartpointer, bei dem die konkrete Art von Ownership nicht bekannt ist. Das Ding wäre nicht kopierbar, dafür aber movebar.
Wozu?
Oftmals ist mir egal, wie das Ding verwaltet wird. Bei Funktionen und Memberfunktionen könnte man das noch über ein Template lösen, aber spätestens wenn das Ding Member einer Klasse ist, wirds unschön.Ein weiterer Vorteil, der sich wohl nur bei größeren Projekten lohnt, ist, dass bei änderung der Ownership, die z.B. von einer Factory zurückgegeben wird, nur ein einziges .cpp File neu kompiliert werden muss. Mit typedef müssen alle Files, die davon abhängen, rekompiliert werden.
Habt ihr sowas schon mal vermisst? Meinungen dazu?
Grüße,
PI
-
std::unique_ptr?
-
Da kann ein unique_ptr, shared_ptr, weak_ptr, some_other_ptr, und theoretisch auch ein roher, nicht besitzender Zeiger drin sein.
-
Nein, wollte ich noch nie. Wenn das Ding Member einer Klasse ist, dann gehört es auch mir, und dann ist mir nicht egal was da drin steckt. Für Parameter etc. nutze ich rohe Pointer.
-
314159265358979 schrieb:
Da kann ein unique_ptr, shared_ptr, weak_ptr, some_other_ptr, und theoretisch auch ein roher, nicht besitzender Zeiger drin sein.
Was ich mit meinem zugegeben etwas kurzen Post sagen wollte: unique_ptr ist doch so ein polymorpher Smartpointer. Oder andersrum: was an std::unique_ptr genügt den Ansprüchen nicht, die du geschildert hast? (oder shared_ptr)
struct Base { virtual ~Base(){} } struct Derived : Base {} int main() { std::unique_ptr<Base> basePretender(new Derived()); }
-
Ich glaub er will nicht einen Smartptr, der mit polymorphen Objekten umgehen kann, sondern einen Smartptr, der so funktioniert, dass z.B. die Klasse, die den Smartptr als Attribut hält, selbst nicht weiß, was für einen Besitzesgrad ggü. dem verwiesenen Objekt der Smartptr hat.
Aber mich würde wirklich gerne Mal ein Szenario interessieren, in dem das hilfreich ist.
-
Wenn du dich um nichts kuemmern moechtest, dir alles egal ist, du keine Ahnung hast, dann nimm Garbage Collection!
-
knivil schrieb:
Wenn du dich um nichts kuemmern moechtest, dir alles egal ist, du keine Ahnung hast, dann nimm Garbage Collection!
So nen Kommentar kannst du dir schenken. Mein Post ist durchaus ernst gemeint.
Es geht darum, dass es (wenn wir mal von Funktionen sprechen) der Funktion vollkommen egal ist, wie das Objekt verwaltet wird. Das einzig wichtige ist, dass sie eines bekommt.
-
Mein Beitrag ist auch ernst gemeint. SmartPointer erleichtern das Verwalten der Ownership und vereinfachen das Bookkeeping und helfen Fehler zu vermeiden. D.h. Du musst dir trotzdem Gedanken ueber Ownership machen. Das nimmt dir der SmartPointer nicht ab.
Es geht darum, dass es (wenn wir mal von Funktionen sprechen) der Funktion vollkommen egal ist, wie das Objekt verwaltet wird. Das einzig wichtige ist, dass sie eines bekommt.
Dann schau dir den Vortrag von Herb Sutter bei Going Native 2012 an: Benutze einfach normale Zeiger oder Referenzen, wenn die Funktion der Lebenszeit des Objektes nichts hinzufuegt.
-
Dangling Pointer ftw. (Vortrag habe ich übrigens gesehen.)
-
314159265358979 schrieb:
Dangling Pointer ftw.
Schreib doch einfach mal ein Codebeispiel in dem du das Problem das du siehst zeigst.
-
Sobald du mehrere Threads hast, kann sowas leicht passieren, wenn man nicht höllisch aufpasst. Ich schreib hier jetzt sicher keine multi-threaded Anwendung.
-
314159265358979 schrieb:
Dangling Pointer ftw.
Wie stellst du dir das vor? Der Pointer soll nichts über den Besitz des Objektes wissen (somit natürlich nicht in die Besitzverhältnisse irgendwie eingreifen), aber trotzdem magisch verhindern, dass es zu früh freigegeben wird?
-
wenn wir mal von Funktionen sprechen ... Dangling Pointer ftw.
Das widerspricht sich. Wenn die Funktion einen Pointer/Referenz entgegennimmt, dass Objekt von aussen nicht zerstoert wird (Funktion ist kuerzer als die Lebenszeit des Objektes), wie kann es dann zu Dangling Pointers kommen?
Ansonsten bleibe ich dabei: Du willst keinen SmartPointer sondern Garbage Collection.
Sobald du mehrere Threads hast
Das erwaehnst du jetzt das erste mal. D,h. die Lebenszeit des Objektes ist nicht genau festgelegt, d.h. eine Funktion in einem anderen Thread kann die Lebenszeit verlaengern, d.h. du musst dir ueber Ownership gedanken machen, zumindest ueber die Lebenszeit. Da mehrere Threads ein Objekte benutzen waere
shared_ptrangemessen.
-
Der Pointer darf ja was darüber wissen, nur soll dieses Wissen für den Funktionsaufruf weggekapselt sein...
knivil: Ok, so... ja, so versteh ich das.
-
314159265358979 schrieb:
Da kann ein unique_ptr, shared_ptr, weak_ptr, some_other_ptr, und theoretisch auch ein roher, nicht besitzender Zeiger drin sein.
Wenn du mich fragst, machst du grad irgendwas falsch wenn du sowas haben willst. So ein Zeiger macht keinen Sinn. Die oben genannten Smart Pointer haben kein gemeinsames Konzept, sie von einer gemeinsamen Basis abzuleiten wär also schon rein logisch falsch.
Ich glaub was du suchst ist einfach nur ein roher Zeiger.
-
dot schrieb:
Die oben genannten Smart Pointer haben kein gemeinsames Konzept
Doch, schon. Alle vermitteln irgendeine Art von Besitz, und bei keinem muss man sich um die Freigabe kümmern.
Trotzdem, ich halte es für sinnvoller sich über den Scope seines Objekts Gedanken zu machen. Was Threads angeht (wo auch immer die plötzlich herkommen oO) würde ich gerne mal ein Beispiel sehen, bei dem das große Vorteile gegenüber shared_ptr hat.
314159265358979 schrieb:
Ich schreib hier jetzt sicher keine multi-threaded Anwendung.
Ja nun, irgendeinen Fall solltest du doch im Kopf haben?
-
cooky451 schrieb:
dot schrieb:
Die oben genannten Smart Pointer haben kein gemeinsames Konzept
Doch, schon. Alle vermitteln irgendeine Art von Besitz, und bei keinem muss man sich um die Freigabe kümmern.
Nein. Ein weak_ptr z.B. besitzt nichts.
-
cooky451 schrieb:
dot schrieb:
Die oben genannten Smart Pointer haben kein gemeinsames Konzept
Doch, schon. Alle vermitteln irgendeine Art von Besitz, und bei keinem muss man sich um die Freigabe kümmern.
Nein, weak_ptr vermittelt keinen Besitz sondern ist nur ein Verweis auf etwas, was vielleicht noch von einem shared_ptr gehalten wird.
-
Ich implementiers einfach mal, vlt wird dann klarer, wie das Ding funktioniert.
template <typename T> struct unknown_ptr { struct ptr_wrapper_base { virtual T& operator * (); virtual T const& operator * () const; virtual T* operator -> (); virtual T const* operator -> () const; virtual ~ptr_wrapper_base() {} }; template <typename Ptr> struct ptr_wrapper : ptr_wrapper_base { Ptr ptr; ptr_wrapper(Ptr ptr) ptr(std::move(ptr)) {} virtual T& operator * () { return *ptr; } virtual T const& operator * () const { return *ptr; } virtual T* operator -> () { return &*ptr; } virtual T const* operator -> () const { return &*ptr; } }; T& operator * () { return **ptr; } T const& operator * () const { return **ptr; } T* operator -> () { return &**ptr; } T const* operator -> () const { return &**ptr; } template <typename Ptr> unknown_ptr(Ptr ptr) : ptr(new ptr_wrapper<Ptr>(std::move(ptr))) {} private: std::unique_ptr<ptr_wrapper_base> ptr; };