
Marcin KaliciƱski wrote:
Hi Everybody,
Smart pointers in boost work on a principle of preventing object destruction while references to it exist anywhere in the system. It causes that whoever owns a boost::shared_ptr to some object, has power to decide for how long will that object live. This is "ownership". In some situations it would be more convenient if object itself decided when to die (owned itself?), and notified all reference holders about this fact, so that they not try to use it any more.
You can do this with shared_ptr/weak_ptr.
A real-life example from a computer game code. There are C++ objects representing tanks on the battlefield. When tank gets hit, it explodes and ceases to exist. The nice, straighforward way to do it is to write "delete this;" in C++. All references to deleted tank which are held by other tanks (for example those currently aiming at it, or following it), will be immediately updated to NULL, provided that they are live_ptrs: [...]
You can make the object own itself by adding a shared_ptr member to it that holds a self-reference (this_). The self-destruction is accomplished with this_.reset(). All weak_ptr instances will "expire". Or you can use a null deleter if you want to delete the object explicitly and not use shared_ptr to manage its lifetime: http://boost.org/libs/smart_ptr/sp_techniques.html#weak_without_shared but this solution has a drawback that I mention below. In practice, my tanks are usually owned by a container (vector< shared_ptr<Tank> > in the simplest case), because I need to enumerate them.
template<class T> class live_ptr { // Member functions closely resembling those of shared_ptr // When object pointed to is deleted, this pointer resets its value to NULL };
The problem with providing such an interface is lack of reentrancy and thread safety. Consider this code: live_ptr<X> px; if( px != 0 ) { px->f(); } If after the px != 0 check the object is deleted by a different thread, px->f() will crash. This can also happen in some complex single threaded code. weak_ptr::lock is designed to prevent this from happening by giving you a shared_ptr to the object which keeps it alive.
class Tank;
void live_ptr_test() { Tank *tank = new Tank; live_ptr<Tank> p(tank); // not ownership, but a "live" reference delete tank; assert(p == 0); }
Your live_ptr<> requires support from Tank, right?