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