473,225 Members | 1,276 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,225 software developers and data experts.

Simple reference counting.

Hi,

Please consider the following class (it's not really my class, but it's
a good example for my question):

class Vector {
int myN;
double *myX;
Vector(int n) : myN(n), myX(new double[n]) { }
double &operator()(int i) { return myX[i]; }
// Some other typical methods;

~Vector() { delete[] myX }
};

This class needs reference counting so that the following would work:

Vector a(5);
Vector b = a;

And I know of a way to do it by defining a class that houses "double
*myX" and counts references and then have "class Vector" contain a
pointer to that ref counting class. That's ok, but I'm concerned that
having an extra pointer to resolve will slow down the access of
elements. (My program has very few Vectors but uses them a lot.)

Two questions:
1. Are my concerns about access time founded?
2. If yes, is there a simpler way to do ref counting e.g. somehow let
Vector count references?

Very many thanks in advance!

Aaron Fude

Feb 2 '06 #1
4 4157
aa*******@gmail.com wrote:
Hi,

Please consider the following class (it's not really my class, but it's
a good example for my question):

class Vector {
int myN;
double *myX;
Vector(int n) : myN(n), myX(new double[n]) { }
double &operator()(int i) { return myX[i]; }
// Some other typical methods;

~Vector() { delete[] myX }
};

This class needs reference counting so that the following would work:

Vector a(5);
Vector b = a;

And I know of a way to do it by defining a class that houses "double
*myX" and counts references and then have "class Vector" contain a
pointer to that ref counting class. That's ok, but I'm concerned that
having an extra pointer to resolve will slow down the access of
elements. (My program has very few Vectors but uses them a lot.)

Two questions:
1. Are my concerns about access time founded?
I would not think so. However, just try it.

2. If yes, is there a simpler way to do ref counting e.g. somehow let
Vector count references?


I don't know if it is simpler, but you can do something like this, I think
(beware, the following is untested code):
#include <algorithm>
#include <memory>

class Vector {

double* data;
unsigned length;
unsigned* ref_count;

public:

Vector ( unsigned l )
{
length = l;
std::auto_ptr< unsigned > ref_count_dummy ( new unsigned );
data = new double [ length ];
ref_count = ref_count_dummy.release();
*ref_count = 1;
}

Vector ( Vector const & other )
: data ( other.data )
, length ( other.length )
, ref_count ( other.ref_count )
{
++ *ref_count;
}

Vector& operator= ( Vector const & other ) {
Vector dummy ( other );
this->do_swap( dummy );
return ( *this );
}

void do_swap ( Vector & other ) {
std::swap( data, other.data );
std::swap( length, other.length );
std::swap( ref_count, other.ref_count );
}

~Vector ( void ) {
-- *ref_count;
if ( *ref_count == 0 ) {
delete [] data;
delete ref_count;
}
}

};

This should speed up access to the vector elements at the cost of making
assignments a little more expensive.

Some comments:

(a) the auto_ptr yadda yadda in the constructor is needed since

data = new double [ length ];

might throw. As there is no auto_array, this also determines the order of
assignments in this constructor.

(b) the swap idiom in the assignment operator is not just to make a strong
exception safety guarantee, it is also the easiest way to get the reference
counting right: the only places that deal with counting are the
constructors and the destructor. That keeps things simple.

(c) You may want to measure whether all this is actually needed. After all,
there is std::vector. Also note that the class above will fail you in a
multithreaded environment. Reference counting is notoriously hard to get
right in the presence of multiple threads.
Best

Kai-Uwe Bux
Feb 2 '06 #2
aa*******@gmail.com wrote:
class Vector {
int myN;
double *myX;
Vector(int n) : myN(n), myX(new double[n]) { }
double &operator()(int i) { return myX[i]; }
// Some other typical methods;

~Vector() { delete[] myX }
};

This class needs reference counting so that the following would work:

Vector a(5);
Vector b = a;
Your class could easily do that without ref counts. What you mean is
that you assume your class needs ref counting in order to do the above
with acceptable performance.
And I know of a way to do it by defining a class that houses "double
*myX" and counts references and then have "class Vector" contain a
pointer to that ref counting class.
Or, y'know, use a general smart pointer like tr1::shared_ptr.
That's ok, but I'm concerned that
having an extra pointer to resolve will slow down the access of
elements.
What do your performance tests tell you?
(My program has very few Vectors but uses them a lot.)
The rule is, make the common case fast. If you aren't creating many
vectors, why are you so concerned with avoiding copying them? Don't
introduce ANY "clever optimizations" until you do performance tests and
discover a need, and even then be sure to check that the "optimization"
actually helped.
1. Are my concerns about access time founded?
Not until your profiler tells you so. Yes, really.
2. If yes, is there a simpler way to do ref counting e.g. somehow let
Vector count references?
tr1::shared_ptr.
Very many thanks in advance!


HTH,
Luke

Feb 2 '06 #3

Luke Meyers wrote:
2. If yes, is there a simpler way to do ref counting e.g. somehow let
Vector count references?


tr1::shared_ptr.


If you mean shared_ptr< vector<T> > then that will work to reference
count the vector. Of course the vector will need to be created
initially with new.

If you mean vector< shared_ptr < T > > that is different, of course.
That is used to avoid copying the T objects, and when you copy the
vector you'll get a vector to the same T instances as before.

Or do you mean shared_ptr< T, array_deleter<T>() > where array_deleter
is a deleter that calls delete[], in which case he is not using vector
at all (Is shared_array part of tr1 by the way?)

Feb 2 '06 #4
aa*******@gmail.com wrote:
Hi,

Please consider the following class (it's not really my class, but it's
a good example for my question):

class Vector {
int myN;
double *myX;
Vector(int n) : myN(n), myX(new double[n]) { }
double &operator()(int i) { return myX[i]; }
// Some other typical methods;

~Vector() { delete[] myX }
};

This class needs reference counting so that the following would work:

Vector a(5);
Vector b = a;
Yes, you'd need a copy constructor and assignment operator (since you
manage resources)
And I know of a way to do it by defining a class that houses "double
*myX" and counts references and then have "class Vector" contain a
pointer to that ref counting class.
So what you're saying is that by copying the Vector, you actually want
reference semantics to the data? That Vector itself has reference
semantics? That modifications to b, also modify a?

Or do you want the copy to be quick (shallow), but when the data is
first modified it must be copied (Copy On Write, COW)?
That's ok, but I'm concerned that
having an extra pointer to resolve will slow down the access of
elements. (My program has very few Vectors but uses them a lot.)
Looks like you're going the wrong way then. You're trading speed of
access to increase speed of copying.
Two questions:
1. Are my concerns about access time founded?
Unlikely.
2. If yes, is there a simpler way to do ref counting e.g. somehow let
Vector count references?


In addition to boost::shared_ptr, you could also use
boost::intrusive_ptr, which has a little less space overhead, but
requires you to inherit from it and store the count yourself.

I'm lazy so I created a base class to do this for me.

You can also use a COW pointer, but that depends on the semantics you
require.

If you really want reference semantics, it's often better to make that
explicit to the user with:
#include <boost/shared_ptr.hpp>

class Vector {};

typedef boost::shared_ptr<Vector> Vector_ptr;

int main()
{
Vector_ptr a(new Vector);
Vector_ptr b(a);
Vector_ptr c = a;

}
Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Feb 2 '06 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Elbert Lev | last post by:
Please correct me if I'm wrong. Python (as I understand) uses reference counting to determine when to delete the object. As soon as the object goes out of the scope it is deleted. Python does...
1
by: ash | last post by:
hi does anyone has any experience with flyweight pattern with refernce counting i want to share objects between multiple clients and want to delete the object from shared pool when the last...
27
by: Jason Heyes | last post by:
To my understanding, std::vector does not use reference counting to avoid the overhead of copying and initialisation. Where can I get a reference counted implementation of std::vector? Thanks.
0
by: Kalle Rutanen | last post by:
Hello I implemented reference counting in my program, and found out many problems associated with it. I wonder if the following problems can be solved automatically rather manually ? 1. ...
1
by: Tony Johansson | last post by:
Hello Experts! I reading a book called programming with design pattern revealed by Tomasz Muldner and here I read something that I don't understand completely. It says "A garbarage...
176
by: nw | last post by:
Hi, I previously asked for suggestions on teaching testing in C++. Based on some of the replies I received I decided that best way to proceed would be to teach the students how they might write...
1
by: oec.deepak | last post by:
Hi Cn any one telll me what is Reference counting in C++.
30
by: galiorenye | last post by:
Hi, Given this code: A** ppA = new A*; A *pA = NULL; for(int i = 0; i < 10; ++i) { pA = ppA; //do something with pA
8
by: mathieu | last post by:
Hi there I have implemented a very simple smartpointer class (invasive design). And I was wondering what should be the natural API when using those in a Container. I choose to define the...
1
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
0
by: VivesProcSPL | last post by:
Obviously, one of the original purposes of SQL is to make data query processing easy. The language uses many English-like terms and syntax in an effort to make it easy to learn, particularly for...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 3 Jan 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). For other local times, please check World Time Buddy In...
0
by: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
2
by: jimatqsi | last post by:
The boss wants the word "CONFIDENTIAL" overlaying certain reports. He wants it large, slanted across the page, on every page, very light gray, outlined letters, not block letters. I thought Word Art...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.