Boost logo

Boost Users :

From: Stephen Crowley (stephenc_at_[hidden])
Date: 2002-11-16 19:13:33


On Thu, Nov 14, 2002 at 11:38:25PM -0800, Duane Murphy wrote:
> --- At Thu, 14 Nov 2002 22:36:40 -0600, Stephen Crowley wrote:
>
> Accessing this here is accessing it as a raw pointer outside of the
> shared_ptr. In a word...dont do that.
>
> I had this problem before but I was able to work around it. I dont have a
> good suggestion for a solution. Basically, architecturally, I arranged to
> not need to save things this way. In my case I ended up actually passing
> in a shared_ptr to solve the problem. You can duplicate a shared_ptr, you
> cant duplicate a raw pointer this way.
>
> I have found this to be a difficult thing to deal with in a couple of
> corner cases. Where I wanted the raw pointer to know that it was shared,
> but I couldnt do that. This would be an intrusive shared_ptr
> implementation rather than the current non-intrusive one. In an intrusive
> implementation, the count information is actually part of the shared
> object rather than an extra pointer. There are certain advantages to the
> intrusive model. Of course it has is draw backs as well.

Hi Duane. Thanks for the help. I considered redesigning my classes so that
using 'this' wouldn't be necessary, however I decided that it would
complicate things unnecessarily.

I've created two new templates calle, one called smart_ptr which is based on
shared_ptr, and one called smart_class.

Basically, when a smart_class is constructed, it initializes thisptr of type
smart_ptr<T> to 'this'. When a smart_ptr is intialized with a standard
pointer(s), either through a constructor or assignment, it first checks to see
whether s->thisptr is initialized. If it is, it simply does a normal copy. If
it isn't initialized, it creates a new shared_ptr to point to it. Also,
smart_ptr checks the reference count every time it is destroyed or
re-assigned, and if the count is 2 then it resets "get()->thisptr" as well,
this is necessary because the smart_class is self referencing and will never
get deleted otherwise.

I've tested it for a while I think I have in working in just about every
case that I need. The only drawbacks are that you cannot instantiate a
smart_class on the stack, or 'delete' it'. Also, you MUST overload the copy
consructor for smart_class derived classes, if this wasn't forced then the
default copy would duplicate thisptr, which obviously isn't what we want.

I can't help but think that I am doing something very weird here, but it
seems to work.

The header and this example code can be found at

http://groups.yahoo.com/group/Boost-Users/files/smart_ptr/

#include "smart_ptr.h"
#include <iostream>

using namespace std;

class MyClass : public smart_class<MyClass>
{
public:
  MyClass() { cout << "constructed " << this << endl; };
  MyClass(MyClass &m) { };
  ~MyClass() { cout << "deleted " << this << endl; };
  
  smart_ptr<MyClass> makeChild() {
    smart_ptr<MyClass> child(new MyClass);
    child->parent = this; // this actually works
    return child;
  }
  
  smart_ptr<MyClass> parent;
};

smart_ptr<MyClass> make_child()
{
  smart_ptr<MyClass> parent(new MyClass);
  return smart_ptr<MyClass>(parent->makeChild());
}

main()
{
  smart_ptr<MyClass> child;
  child = make_child();
  cout << "child = " << child.get() << " child->parent = " << child->parent.get() << endl;
  cout << "resetting child->parent, it should be deleted as the last reference is gone" << endl;
  child->parent.reset();
  cout << "all done, child should be deleted when main() exits" << endl;
}

-- 
Stephen

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net