RAII mit Smart Pointer
-
Abend,
habe gerade diesen Artikel: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Resource_Acquisition_Is_Initialization
zu RAII gelesen und da wird gesagt, dass man RAII mit std::auto_ptr und boost::scoped_ptr implementieren kann. Ok, leuchtet mir ein. Aber wieso wird da nicht auch boost::shared_ptr erwähnt? Damit funktioniert doch genauso RAII?
-
Kann man schon auch, aber ein
shared_ptr
kann eben noch einiges mehr und ist nicht direkt dafür gedacht, wohingegenauto_ptr
oderscoped_ptr
geeignet sind RAII direkt umzusetzen.shared_ptr
hat lediglich dafür einen zu grossen Overhead (verteilte Besitzverhältnise).
-
scoped_ptr
ist im Prinzip der RAII-Smart-Pointer. Er macht nichts anderes als am Ende des Scopes automatischdelete
aufzurufen.Wie schon von drakon angetönt, ist er im Bezug auf RAII daher um einiges anschaulicher als
shared_ptr
, welcher nebenbei noch Reference-Counting, benutzerdefinierte Deleter, Derived-to-Base-Konvertierungen, Threadsicherheit, eine Art Pimpl für unvollständige Typen, die Unterscheidung schwacher/starker Verweise mitweak_ptr
und Spezialverhalten für das eigene Objekt mitenable_shared_from_this
umsetzt. (Da wird einem bewusst, wie komplexshared_ptr
eigentlich ist... ;))
-
Dieser shared_ptr benutzt ja non-intrusive ref counting. Kann ich mir mal irgendwo eine Beispielimplementierung von shared_ptr anschauen? Würde gern mal sehen, wie das mit dem Ref Counter bei non-intrusive funktioniert (Will mir aber nicht den original boost Code anschauen. Der is zu komplex und optimiert. Mir gehts nur ums Prinzip)
-
Also "Modern C++ Design" von Alexandrescu hat ein Kapitel über Smart Pointer.
Online gibts bestimmt auch gute Erklärungen, aber müsste ich auch zuerst suchen.
-
Du hast neben dem Speicherbereich für das Objekt einen zweiten Speicherbereich, der ebenfalls geteilt wird und nur eine Zahl (Anzahl der Referenzen) mit Initialwert 1 enthält. Bei der Kopie eines
shared_ptr
s wird diese Zahl erhöht. Im Destruktor wird die Zahl erniedrigt, und falls sie 0 erreicht (letztershared_ptr
wird zerstört), wird das Objekt zerstört und freigegeben.
-
Könnte jemand vielleicht schnell ein bißchen Code einer möglichst simplen shared_ptr Implementierung schreiben? Also nur das Notwendigste (Member, Ctor, Dtor und operator= denk ich mal)
-
Du hast Glück, dass ich sowas schon mal gemacht und sogar den Thread wiedergefunden habe
http://www.c-plusplus.net/forum/262675
-
Etwa so, denke ich:
template<typename t> class shared_ptr { public: shared_ptr() : myObject(NULL), myCounter(NULL) { } shared_ptr( t* Object ) : myObject(Object), myCounter(new int(1)) { } shared_ptr( const shared_ptr& Other ) { take( Other ); } ~shared_ptr() { release(); } shared_ptr& operator=( const shared_ptr& Other ) { release(); take( Other ); } protected: void take( const shared_ptr& Other ) { myObject = Other.myObject; myCounter = Other.myCounter; if ( myObject ) ++*myCounter; } void release() { if ( ! myObject ) return; if ( --*myCounter == 0 ) { delete myObject; delete myCounter; } myObject = NULL; myCounter = NULL; } private: t* myObject; int* myCounter; };
-
Vielen Dank euch beiden!
@Nexus: Fehlt bei deinem operator= nicht noch eine Dekrementierung von m_refcount? So wie ich das sehe setzt du doch nur die Member von this auf die Werte vom übergebenen rhs, aber du dekrementierst nirgends den Wert von this->m_refcount, oder?
-
RaderZweite schrieb:
@Nexus: Fehlt bei deinem operator= nicht noch eine Dekrementierung von m_refcount?
Nein, er macht copy&swap.
Da hat er im dtor das decrement und im ctor das increment
-
Der Code ist schon recht alt (war er schon zum Zeitpunkt des Posts), ich hab ihn nur mal geschrieben, um etwas herumzuexperimentieren und die Hintergründe besser zu verstehen. Eingesetzt wurde er nie, wirklich getestet auch nicht.
Der Schnipsel entspricht auch nicht 1:1 dem Originalcode, ich habe dazumals einige Dinge vereinfacht (und auch kleinere Schreibfehler gemacht :)).
-
Nexus schrieb:
scoped_ptr
ist im Prinzip der RAII-Smart-Pointer. Er macht nichts anderes als am Ende des Scopes automatischdelete
aufzurufen.Im Zusammenhang damit sollte man evtl. auch den unique_ptr erwähnen.
unique_ptr
ist im Prinzip der RAII-Smart-Pointer ab C++0x.