Schlanke Smartpointer-Implementierung?
-
Shade Of Mine schrieb:
Zeig doch ein bisschen respekt.
Wenn er sich absichtlich dumm stellt...
Shade Of Mine schrieb:
Worum es geht ist Intrusiv-Verhalten. Das ist in vielen Situationen ziemlich ideal. zB wenn man eine Resource eh nur per Smartpointer verwalten wird.
Fahre fort.
Shade Of Mine schrieb:
make_shared macht ja auch nichts viel anderes als intrusiv zu sein, nur dass make_shared halt ein boeser Hack ist.
Wie bitte? Also entweder, du hast make_shared nicht verstanden, oder ich dich nicht. Erklär mal genauer, wie du das meinst.
-
314159265358979 schrieb:
Shade Of Mine schrieb:
Zeig doch ein bisschen respekt.
Wenn er sich absichtlich dumm stellt...
Ich stell mich nicht absichtlich dumm. Dafür bist du gerade wieder dabei in den "ich weiss was ich weiss was ich weiss was ich weiss was ich weiss was!!!!" Modus zu schalten, der dir dann jedes mal das Gehirn rausschmilzt.
Zurück zum Thema:
Nur weil das Objekt den Reference-Count "enthält" heisst dass noch lange nicht dass es "sich selbst besitzt".
-
314159265358979 schrieb:
Shade Of Mine schrieb:
Worum es geht ist Intrusiv-Verhalten. Das ist in vielen Situationen ziemlich ideal. zB wenn man eine Resource eh nur per Smartpointer verwalten wird.
Fahre fort.
Was gibts da noch zu erklaeren? Intrusiv-Verhalten spart allokationen und erhoeht Cache-Lokalitaet. Das ist ne gute Sache.
Shade Of Mine schrieb:
make_shared macht ja auch nichts viel anderes als intrusiv zu sein, nur dass make_shared halt ein boeser Hack ist.
Wie bitte? Also entweder, du hast make_shared nicht verstanden, oder ich dich nicht. Erklär mal genauer, wie du das meinst.[/quote]
Dirty Hack ist vielleicht uebertrieben - aber es hat seine Kosten dass nur eine Allokation statt 2 stattfindet. make_shared allokiert einen Block an Speicher und erstellt dort drin 2 Objekte. Das bedeutet, dass wir zB keinen eigenen allocator fuer unsere Klasse verwenden koennen, wir koennen auch deshalb keinen eigenen deleter verwenden. Wir koennen das Objekt auch nicht aus dem shared_ptr raus nehmen, wenn wir es nicht mehr laenger dort verwalten lassen wollen,...
make_shared hat viele Nachteile. Natuerlich sind diese Nachteile in fast jeder Situation durch den Performance Gewinn aufgehoben - aber ganz so toll ist make_shared doch nicht.
Eine andere Loesung das make_shared Problem zu loesen ist die Klasse direkt intrusiv zu verwenden. Das wuerde viele Probleme von make_shared loesen (und natuerlich auch selber wieder andere haben).
Aber wir diskutieren hier nicht wirklich ob intrusive Datenstrukturen sinnvoll sind, oder?
-
Shade Of Mine schrieb:
make_shared hat viele Nachteile. Natuerlich sind diese Nachteile in fast jeder Situation durch den Performance Gewinn aufgehoben - aber ganz so toll ist make_shared doch nicht.
Welche vielen Nachteile sind das? Die Sache mit dem verzögertem Freigeben des Speichers im Falle von weak_ptrs könnte man wahrscheinlich als Nachteil auffassen. Aber wann spielt der denn in der Praxis überhaupt eine Rolle? Doch in fast keiner Situation, würde ich mal behaupten. Was gibt's denn noch an Nachteilen?
-
krümelkacker schrieb:
Was gibt's denn noch an Nachteilen?
Sagt er doch:
Shade Of Mine schrieb:
aber es hat seine Kosten dass nur eine Allokation statt 2 stattfindet. make_shared allokiert einen Block an Speicher und erstellt dort drin 2 Objekte. Das bedeutet, dass wir zB keinen eigenen allocator fuer unsere Klasse verwenden koennen, wir koennen auch deshalb keinen eigenen deleter verwenden. Wir koennen das Objekt auch nicht aus dem shared_ptr raus nehmen, wenn wir es nicht mehr laenger dort verwalten lassen wollen,...
-
Es gibt meines Wissens noch allocate_shared, was einen eigenen Allocator entgegen nimmt. Das "Herauslösen" aus einem shared_ptr ist so oder so nicht vorgesehen und würde ich als Hack einstufen.
-
20.7.2.2.6 shared_ptr creation [util.smartptr.shared.create]
template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); template<class T, class A, class... Args> shared_ptr<T> allocate_shared(const A& a, Args&&... args);Requires: The expression ::new (pv) T(std::forward<Args>(args)...), where pv has type void* and points to storage suitable to hold an object of type T, shall be well formed. A shall be an allocator (17.6.3.5). The copy constructor and destructor of A shall not throw exceptions.
Effects: Allocates memory suitable for an object of type T and constructs an object in that memory via the placement new expression ::new (pv) T(std::forward<Args>(args)...). The template allocate_shared uses a copy of a to allocate memory. If an exception is thrown, the functions have no effect.
Returns: A shared_ptr instance that stores and owns the address of the newly constructed object of type T.
Postconditions: get() != 0 && use_count() == 1
Throws: bad_alloc, or an exception thrown from A::allocate or from the constructor of T.
Remarks: Implementations are encouraged, but not required, to perform no more than one memory allocation. [ Note: This provides efficiency equivalent to an intrusive smart pointer. — end note ]
[Note: These functions will typically allocate more memory than sizeof(T) to allow for internal bookkeeping structures such as the reference counts. — end note ]
-
Alexandrescu, "Modern C++ Design", falls Du darus Zugriff hast. Da ist alles sehr gut erklärt, so dass Du Dir eine speichereffiziente Implementierung schreiben kannst. Ausserdem sparst Du Dir die Forenscharmützel.
-
So, mal wieder angebracht: Ich will jetzt keinerlei Beleidigungen etc. mehr lesen, diskutiert sachlich oder lasst es bleiben. Gilt nicht nur für PI, sondern für alle.
-
... hat es sogar public gestellt:
-
pumuckl schrieb:
Gilt nicht nur für PI, sondern für alle.
Womit hab ich die Ausnahme, extra genannt zu werden, verdient?