[comp.lang.c++] Want pointers on intelligent pointers

marcap@antares.concordia.ca ( MARC ANDREW PAWLOWSKY ) (03/15/91)

I am trying to make a smart class so objects will not delete themselves
if someone is pointing to them.

I have been following the discussion so far and came up with
the following:

Each object keeps a counter which indicates how many objects
are pointing to it. To keep the counter valid it is necessary
for the class to have its own copy, and reference routines.

when the object is to de deleted, the counter is decremented.  If
the counter is less than or equak to zero then all the objects
which are pointed to by the object to are deleted, then the object
is deleted

I have successively done this in C, but am having trouble doing this
in C++.

The trouble is that I would like for my deletion routine to be the
destructor.  But if my interpetation of ARM is correct then the 
destuctor will destroy the object no matter what I do.

Is there a way to have the destructor return without the object being
destroyed.

Next beginners question:

In my creation routines can I refer the the object being created?
I have a class Box which has a global variable called "default_box".
I also have a function "operator =" that will copy a box into
this.  can I do something like

Box::Box(void) {
    this = default_box; // does not work with TC++ 1.01
    return this; // return not allowed
}


 could not find an answer one way or the other in ARM or the TC++ manuals.


Thanks in advance
   Marc Pawlowsky

Jim.Spencer@p510.f22.n282.z1.edgar.mn.org (Jim Spencer) (03/17/91)

 marc Andrew Pawlowsky writes in a message to All

 MA> The trouble is that I would like for my deletion routine to be 
 MA> the destructor. But if my interpetation of ARM is correct then 
 MA> the destuctor will destroy the object no matter what I do.

Novice curiosity here.  Why do you want your deletion routine to be the destructor?  Presumably you are calling the destructor yourself, at least indirectly with delete.  If so, instead of calling delete, call another member function, say check_delete().  This in turn could call the destructor couldn't it?
 

mittle@blinn.watson.ibm.com (Josh Mittleman) (03/19/91)

In article <838@antares.Concordia.CA>, marcap@antares.concordia.ca (
MARC ANDREW PAWLOWSKY ) writes:

I think you're may be going about the reference count backward.  The
reference count is controlled by the smart pointer, not the object.
Consider this approach.

class Object {
friend class ObjectP;
protected:
  int refcount;
  Object() 			{ refcount = 1; }
public:
  ~Object();
};

class ObjectP {
protected:
  Object* myOb;
public:
  ObjectP()	  		{ myOb = new Object(); }
  ObjectP(const ObjectP& ObP);	{ myOb = ObP.myOb; myOb->refcount++; }
  ~ObjectP();			{ if (myOb->refcount == 1)
				     delete myOb;
				  else
				     myOb->refcount--;
				}
};

ObjectP::ObjectP() {
  myOb = new Object();
}

When you need an Object, you actually declare an ObjectP.

> In my creation routines can I refer the the object being created?
> I have a class Box which has a global variable called "default_box".
> I also have a function "operator =" that will copy a box into
> this.  can I do something like
> 
> Box::Box(void) {
>     this = default_box; // does not work with TC++ 1.01
>     return this; // return not allowed
> }

The first line is an anachronism (see ARM, p.406, Assignment to this).  The
type of this in the class Box is Box *const (ARM, p.177).

The C++ approach would be to include a field-by-field assignment in Box,
like this:

Box::Box() {
  width = 50;
  height = 20;
}

This code does refer to the object being constructed, by referencing its
members.  Constructors do not return anything in C++.  On the other hand,
the operator new does.  This is correct:

Box *B = new Box;

===========================================================================
Josh Mittleman (mittle@ibm.com or joshua@paul.rutgers.edu)
J2-C28 T.J. Watson Research Center, PO Box 704, Yorktown Heights, NY  10598

jbuck@galileo.berkeley.edu (Joe Buck) (03/19/91)

In article <838@antares.Concordia.CA>, marcap@antares.concordia.ca ( MARC ANDREW PAWLOWSKY ) writes:
|> I am trying to make a smart class so objects will not delete themselves
|> if someone is pointing to them.
|> 
|> I have been following the discussion so far and came up with
|> the following:
|> 
|> Each object keeps a counter which indicates how many objects
|> are pointing to it. To keep the counter valid it is necessary
|> for the class to have its own copy, and reference routines.

You're close.  But you need two classes, SmartClassRep stores the
actual data and SmartClass stores a pointer to it.  When you copy
SmartClass objects around you adjust the reference count.  Here's
part of the job:

class SmartClassRep {
	friend SmartClass;
	// make all members private
	int refCount;
	SmartClassRep() : refCount(0) { ... }
};

class SmartClass {
private:
	SmartClassRep *p;
public:
	// assignment operator
	SmartClass& operator=(const SmartClass& arg) {
		arg.p->refCount++;
		if (--p->refCount == 0) delete p;
		p = arg.p;
	}
	// copy constructor
	SmartClass(const SmartClass& arg) {
		p = arg.p;
		p->refCount++;
	}
	// destructor
	~SmartClass() {
		if (--p->refCount == 0) delete p;
	}
}

--
Joe Buck
jbuck@galileo.berkeley.edu	 {uunet,ucbvax}!galileo.berkeley.edu!jbuck	

marcap@antares.concordia.ca ( MARC ANDREW PAWLOWSKY ) (03/20/91)

In article <669258004.1@mmug.edgar.mn.org> 
Jim.Spencer@p510.f22.n282.z1.edgar.mn.org (Jim Spencer) writes:

in response to my call for help
>
>Novice curiosity here.  Why do you want your deletion routine to be 
> the destructor?  Presumably you are calling the destructor yourself, 
> at least indirectly with delete.  If so, instead of calling delete, 
> call another member function, say check_delete(). 
> This in turn could call the destructor couldn't it?
> 

The idea I was thinking was something like:

A *A::a(void) {
    ...
    create a new instance of A and return it.
}

A::b(void) {

    A a = a();

    put a into some global data structure such as a linked list.
}

The linked list would be in use, and it is necessary to keep track
how many times the objects are being used.

While I can call a function other than delete, I thought it would be nice
to use destructor oeprator since other people will be using my classes, so
if somebody did


C::c(void) {

    A a;

... all sorts of nifty things

}

"a" would be deleted properly, even though no explicit destuction routine is 
called.

Jim.Spencer@p510.f22.n282.z1.fidonet.org.org (Jim Spencer) (03/21/91)

 marc Andrew Pawlowsky writes in a message to All

 MA> The linked list would be in use, and it is necessary to keep 
 MA> track how many times the objects are being used. 
 MA> While I can call a function other than delete, I thought it would 
 MA> be nice to use destructor oeprator since other people will be 
 MA> using my classes, so if somebody did 
 MA>  C::c(void) { 
 MA>  A a; 
 MA> ... all sorts of nifty things 
 MA> } 
 MA> "a" would be deleted properly, even though no explicit destuction 
 MA> routine is called. 

Sorry, I don't mean to be dense, but the A created in C::c() would not be the one in your linked list: it will have been specifically created for use in c() and should be disposed of at the end of c().
 

jimad@microsoft.UUCP (Jim ADCOCK) (03/23/91)

In article <1991Mar18.220013.18185@watson.ibm.com> mittle@ibm.com writes:
|
|In article <838@antares.Concordia.CA>, marcap@antares.concordia.ca (
|MARC ANDREW PAWLOWSKY ) writes:
|
|I think you're may be going about the reference count backward.  The
|reference count is controlled by the smart pointer, not the object.

These issues are well covered in Hansen's "The C++ Answer Book" --
if I remember right.