Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

reference counting in C++

75 views
Skip to first unread message

Mark Suska

unread,
Nov 7, 1996, 3:00:00 AM11/7/96
to

One thing I would like to see in a language is reference counting. This
minimal form of garbage collection adds little overhead and can clean up
everythig except for circular references.
I do not believe that a programmer should be focussing on propper
deallocation of resources. Wouldn't it be nice if after an object was
not being used that it would deallocate itself or that a file would
close itself.

Is it possible to overload the = operator so that it will perform
reference counting of an object? For example,

a = b;

would increment the count for the object that b is refering to because a
now points to it, at the same time the count would be decremented for
the object that a refers to before the = operation. If the reference
count is decremented to zero the object will destruct itself.

How could the first time initialization of a variable be handled? For
example,

// initialize a for the first time
a = new A;

The reference count of a before the operation can not be decremented
because its value is invalid.

There is a similar problem when a variables leaves scope. The variable
is no longer in use, the reference count should be decremented. Is
there a way to do this automatically? Example:

{
A *a = new A;

// a leaves its scope without decrementing its reference count
}

Any ideas, or is this just imposible in C++?

Thanks,
Mark

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]


Randy Morin

unread,
Nov 7, 1996, 3:00:00 AM11/7/96
to

I have an alternate solution. What I've done is written a reference
counting template class called RefCount<...>. It performs all the
benefits that you've mentionned and more. I can't legally reproduce
that code here, but Scott Meyers has similar but less effective
templates in his book "More Effective C++". Meyers' template were
the starting point for my more effective version.

Randy Charles Morin
----------
From: Mark Suska <msu...@chrysalis-its.com>
Date: November 07, 1996 10:15 AM
To: comp.lang.c++
Subject: reference counting in C++

Tom Keane

unread,
Nov 8, 1996, 3:00:00 AM11/8/96
to

Mark Suska wrote:
>
> One thing I would like to see in a language is reference counting. This
> minimal form of garbage collection adds little overhead and can clean up
> everythig except for circular references.
>
> [snip]

>
> Any ideas, or is this just imposible in C++?
>

Sure - use the Counted Pointer Idiom.

For more detail see:
Stroustrup - The C++ Programming Language
Meyers - More Effective C++ ( I'm pretty sure he covers it)
Coplien - Advanced C++ - Programming Styles and Idioms.
Buschmann, et al - A System of Patters -

{ example from Buschmann }

class Body {
public:
// public member functions for Body
void service();

private:
friend class Handle;

Body( /* args */ ); // Ctor is only availble to Handle.
~Body(); // likewise for dtor

int refCount_;
};


class Handle {
public:
Handle( /* args for Body's ctor */ ); {
body= new Body( /* args */ );
body->refCount_= 1;
}

Handle( const Handle & h ) {
body_ = h.body_;
bofy_->refCount_++;
}

Handle & operator=( const Handle & h ) {
h.body->refCount_++;
if (--bofy.refCount_ <= 0)
delete body;
body_= h.body_;
}

~Handle() {
if (--body_->refCount_ <= 0)
delete body_;
}

Body * operator->() { return body_; }

private:
Body * body_;
};

The use of this would as follows:

int main()
{
Handle h( /*some args*/ ); // creates a new Handle & new body

{
Handle g( h ); // New handle, same body as h
g->service();
} // g goes out of scope, decrements refCount
h->service();
} // h goes of scope, body is deleted.


Hope this helps,
Tom Keane

BTW - The books mentioned above are all well worth reading.

Thomas A. Horsley

unread,
Nov 8, 1996, 3:00:00 AM11/8/96
to

>> Any ideas, or is this just imposible in C++?
>
>Sure - use the Counted Pointer Idiom.

This is easy enough to do if you are in control of the class you want to
reference count, but I was wondering just the other day how I might be able
to take advantage of various STL classes and also reference count them
(maybe I want a reference counted string or a reference counted vector).

I keep thinking there might be some way to do something clever with templates
or allocators or something, but when it comes down to it, I can't think
of any way to make a reference counted string without creating some kind of
wrapper class that duplicates the interface and has built in knowledge of
which functions cause the string contents to be modified (and thus need to
make a copy if the refcount is greater than 1) and which functions are only
reading info from the string.

Are there any folks out there who can think of a cleverer way to do this?
--
--
See <URL:http://ourworld.compuserve.com/homepages/TomHorsley> for
information on Government by Performance

Brad Stuart

unread,
Nov 8, 1996, 3:00:00 AM11/8/96
to

Mark Suska (msu...@chrysalis-its.com) wrote:
: One thing I would like to see in a language is reference counting.
This
: minimal form of garbage collection adds little overhead and can clean
up
: everythig except for circular references.

Reference counting pointer classes are pretty common. I copied mine
from Coplien's _Advanced C++_.

You need to make sure users of you class are aware of the semantics of
your shared memory class. Will you copy when a non-const method is
called, or allow "aliasing" like normal C pointers?

Also, you need separate classes for pointers and arrays. For my array
class, I've implemented [] operations; for the basic pointer I have
defined "->" .


| Brad Stuart br...@cfar.umd.edu
| Center for Automation Research
| University of Maryland, College Park

Steve Heller

unread,
Nov 8, 1996, 3:00:00 AM11/8/96
to

Mark Suska <msu...@chrysalis-its.com> wrote:

>One thing I would like to see in a language is reference counting. This
>minimal form of garbage collection adds little overhead and can clean up
>everythig except for circular references.

>I do not believe that a programmer should be focussing on propper
>deallocation of resources. Wouldn't it be nice if after an object was
>not being used that it would deallocate itself or that a file would
>close itself.

Yes, this is nice. It is also not terribly hard to implement in C++;
any good tutorial book on the language will shouw you how to do it.

Steve Heller, author and software engineer
http://ourworld.compuserve.com/homepages/steve_heller

Christian Luginbuehl

unread,
Nov 8, 1996, 3:00:00 AM11/8/96
to

In article <55suf6$8...@netlab.cs.rpi.edu>, msu...@chrysalis-its.com wrote...

>
>One thing I would like to see in a language is reference counting. This
>
>Any ideas, or is this just imposible in C++?

Buy "More Effective C++" from Scott Meyers. He discusses reference
counting in depth.

Cheers, Christian.

--
Christian Luginbuehl lugi...@simultan.ch
Simultan AG, Altishofen, Switzerland.

Bill Hubauer

unread,
Nov 8, 1996, 3:00:00 AM11/8/96
to

In article <55suf6$8...@netlab.cs.rpi.edu> Mark Suska,
msu...@chrysalis-its.com writes:

>There is a similar problem when a variables leaves scope. The variable
>is no longer in use, the reference count should be decremented. Is
>there a way to do this automatically? Example:
>
>{
> A *a = new A;
>
> // a leaves its scope without decrementing its reference count
>}
>

>Any ideas, or is this just imposible in C++?
>


You can do what you want to do easily with smart pointers.
I have two different implementations of exactly what you want.

Here is how one works (Note, this is not a 100% complete implementation,
but it should give you the idea)

First you have a ref count base class something like this:

class RefCounted
{
public:
RefCounted() : fCount(0) {}
virtual ~RefCounted() {}

AddReference() { fCount++; }
RemoveReference() { fCount--; if(!fCount) delete this;}

private:
long fCount;
};

Next you have a smart pointer object like this:
(take note of the copy constructors and assignment operators)

template <class RefCountedSubClass>
class RefPtr
{
public:

RefPtr() : _obj(NULL) {}
RefPtr(const RefPtr& inCopyThis)
{ AddNew(inCopyThis._obj); }
RefPtr(RefCountedSubClass* inPointToThis)
{ AddNew(inPointToThis); }
~RefPtr()
{ RemoveOld(); }

void operator=(const RefPtr& inCopyThis)
{ RemoveOld(); AddNew(inCopyThis._obj); }
void operator=(RefCountedSubClass* inPointToThis)
{ RemoveOld(); AddNew(inPointToThis); }

base* operator->()
{ return _obj; }


private:
void RemoveOld()
{ if(_obj != NULL) _obj->_RemoveReference(); }
void AddNew(RefCountedSubClass inNew)
{ _obj = inNew; if(_obj != NULL) _obj->_AddReference();}

RefCountedSubClass* _obj;
};


Here is how you use it:

class MyClass : public RefCounted
{
// my class members here

};


void MyFunction()
{
RefPtr<MyClass> p = new MyClass;

AnotherFunction(p); // p is copied so MyClass::AddReference is called
// when the copy of p in "AnotherFunction"
// goes out of scope, MyClass::RemoveReference is called

// when this function's copy of p goes out of scope,
// MyClass::RemoveReference is called again and
// this time it deletes itself since the count
// has gone to zero.
}


BENFITS: Cheap effecient garbage collection. Removes "ownership" issues
from your design.
PITFALLS: Class needs to derive from special RefCounted class.
Its not easy to mix smart pointers and real pointers.
The RefPtr template only knows about the class that
it was instansiated with and you cannot cast it
to a subclass of that type.

It works best on monomorphic classes and polymorphic class
who's derived classes all share the same base class
interface. (they don't add new public members)

This technique has proven very useful to me and I hope you
find it useful as well.

Bill Hubauer
Power On Software

Olivier Jautzy

unread,
Nov 9, 1996, 3:00:00 AM11/9/96
to

You can easely implement reference counting in C++. In the C++ STL there
is a template class named auto_ptr that realize that. However, there is
also a very good book from J.O. Coplien : "advanced C++ : Programming
styles and idioms" , Addison Wesley Publishing Company, 1994. This book
explains well how you can realize reference counting and much more.

I hope, this will help you

Bye,
--
Olivier Jautzy INRIA Sophia Antipolis
Tel : 04 93 65 77 46, E-Mail : Olivier...@sophia.inria.fr
Url : http://www.inria.fr/cermics/dbteam/team/Olivier.Jautzy/
** ************** **
** Le prix de la liberti, c'est l'iternelle vigilance (WC3) **

Mike Spertus

unread,
Nov 12, 1996, 3:00:00 AM11/12/96
to

Mark Suska wrote:
>
> One thing I would like to see in a language is reference counting. This
> minimal form of garbage collection adds little overhead and can clean up
> everythig except for circular references.
> I do not believe that a programmer should be focussing on propper
> deallocation of resources. Wouldn't it be nice if after an object was
> not being used that it would deallocate itself or that a file would
> close itself.
>
How about actual garbage collection rather than reference counting. C
and C++
garbage collectors are widely available. They are completely transparent
and
don't require you to wrap your pointers. Garbage collection has lower
overhead
than reference counting (in both time and space). Unlike reference
counting,
garbage collection doesn't get confused by circular references, pointers
stored
in integers, interior pointers, or objects that are not in the heap.
Unlike
reference counting, garbage collectors can fix memory errors in
third-party
libraries and DLLs without recompiling them or access to their source.

For these reasons, Bjarne Stroustrup has written "optional garbage
collection, I think, is the right approach for C++" and that he expects
to
see an increase in the use of garbage collectors in C++ over the next
few
years and that "For many applications automatic garbage collection is
indeed a very powerful tool and the right tool for the job."


See http://www.geodesic.com and
http://www.centerline.com/people/chase/GC/GC-faq.html
for more information on C++ garbage collection as well as pointers to
implementations. (Disclaimer: I make my living selling C/C++ garbage
collectors).

Regards,

Mike

Michael Spertus
Geodesic Systems
4745 N Ravenswood, Suite 111
Chicago, IL 60640

m...@geodesic.com
(773) 728-7196
http://www.geodesic.com

James Fowler

unread,
Nov 13, 1996, 3:00:00 AM11/13/96
to

>>> Any ideas, or is this just imposible in C++?
>>
>>Sure - use the Counted Pointer Idiom.
>

One more book recommendation : "Ruminations on C++" by Andrew Koenig and
Barbara Moo has a good section on reference counting (referred to as
use-counted handles). I'll also second the recommendation on Meyer's "More
Effective C++"/

>I keep thinking there might be some way to do something clever with templates
>or allocators or something, but when it comes down to it, I can't think
>of any way to make a reference counted string without creating some kind of
>wrapper class that duplicates the interface and has built in knowledge of
>which functions cause the string contents to be modified (and thus need to
>make a copy if the refcount is greater than 1) and which functions are only
>reading info from the string.

There are some clever techniques you can combine, but nothing I know of is
going to magically pull this off. The heart of the problem (as I understand
it) is that you can make a pure template solution to provide a handle (even on
a class that doesn't contain the count) but you can't make it automatically
assume the interface of the class you're wrapping. Using operator-> can help
some, but isn't perfect. The biggest problem is that it doesn't cover things
like operator overloading, i.e.

MyString a("a"); // clean, simple construction
MyString b("b");
MyString c(a+b); // intuitive use of overloaded operators

typedef CountedPointer<MyString> CountedString;
CountedString a( new MyString("a") ); // awkward construction -
CountedString b( new MyString("b") ); // must call new
CountedString c(a+b); // oops - doesn't work at all!

Ideally, you want to be able to use "clean" syntax. To do that with reference
counted classes usually means you have to duplicate interface in the handle
class. Not fun, but for any class that will be used heavily it's almost
always worth it.

If you want to count a class and you _don't_ need support for any form of
operator overloading (keep in mind this includes things like stream IO
functions!) and you don't mind feeding constructors with calls to new (and
only calls to new... feed it an address on the stack or of a static and you
won't like the results) and, and, ... you get the picture - you're usually
better off doing the work and putting the interface in the handle class. But
if after all that you still insist, you can crudely provide support for "copy
on write" as you mentioned above by providing a const version of operator->
which just returns the implementation pointer and a non-const version which
does the copy first.

James Fowler, Software Engineer Client Services
voice : (770)242-9998 fax : (770)242-9858
Pager : (800)314-6896 jfo...@roguewave.com
------------------
Bringing you the best in C++ and Java components,
from the experts at Rogue Wave Software, Inc.
check out our homepage - http://www.roguewave.com

Robert Jacobs

unread,
Nov 13, 1996, 3:00:00 AM11/13/96
to

I have seen reference counting implemented on source code that
we bought from a vendor. The user level interface was of objects
not pointers so.

I am not showing functions, just the data structures to do
the job.

Constructors, Destructors variants of = += etc have to handle
modifying the reference count.

Class impA
{
int count;
// Whatever A is supposed to hold.
}

class A
{
class impA *imp;
}

{
A a(some_args); // a.count = 1
{
A b(some_other_args); // b.count = 1
b = b; // b.count=0 then b.count=1 then check
// for reference.
// What is wrong with circular
// reference?

a = b; // old a.count=0 b.count=2
} // b.count=1

} // b.count = 0

Notice that if you use pointers to a or b you will not
be modifying the reference count.

The user thinks he is doing an expensive copy when he really is.
just copying pointers.


--
Robert Jacobs
bo...@mss.com
908-981-1290

Lars Farm

unread,
Nov 13, 1996, 3:00:00 AM11/13/96
to

Mike Spertus <m...@geodesic.com> wrote:

> How about actual garbage collection rather than reference counting.

Andrew Koenig mentioned briefly in a GC thread this summer that GC, one
way or other, was on the agenda for the July committee meeting. I wonder
what came out of that.

--
Lars Farm, lars...@ite.mh.se

0 new messages