Introduction
Shared pointer is a class which can share the underlying data between object. This avoids deep copying and improves performance. It is also called as shallow copying.
Smart pointer is a class which manages the life time of the underlying pointer.
A simple smart pointer class
Lets create a simple base class for smart pointer class using c++ template so that we can store any type of data.
The basic idea of a shared pointer or a smart pointer is that actual data is stored separately and the shared pointer or smart pointer class will have a pointer to it.
For a very basic shared pointer class will have the data class as,
class Data
{
public:
int mRefCount;
T mData;
};
template < typename T >
class RSharedObject
{
protected:
class Data
{
public:
int mRefCount;
T mData;
};
public:
RSharedObject()
: mData(0)
{}
RSharedObject(RSharedObject const & o)
{
mData = 0;
copy(o);
}
RSharedObject& operator=(RSharedObject const & o)
{
copy(o);
return *this;
}
// ...
};
template <typename T >
class RSharedObject
{
protected:
class Data
{
public:
int mRefCount;
T mData;
};
public:
RSharedObject()
: mData(0)
{}
RSharedObject(RSharedObject const & o)
{
mData = 0;
copy(o);
}
RSharedObject& operator=(RSharedObject const & o)
{
copy(o);
return *this;
}
virtual ~RSharedObject()
{
dispose();
}
protected:
virtual T & data_p()
{
if (!mData) {
create();
}
return mData->mData;
}
virtual const T & data_p() const
{
if (!mData) {
const_cast *>(this)->create();
}
return mData->mData;
}
void copy(RSharedObject const & oth)
{
dispose();
mData = oth.mData;
ref();
}
void detach()
{
if (mData && mData->mRefCount > 1) {
deref();
mData = new Data(*mData);
mData->mRefCount = 1;
}
}
private:
void create()
{
mData = new Data();
ref();
}
void dispose()
{
if (mData) {
deref();
if (mData->mRefCount == 0) {
delete mData;
mData = 0;
}
}
}
void ref()
{
if (mData) {
++mData->mRefCount;
}
}
void deref()
{
if (mData) {
--mData->mRefCount;
}
}
private:
Data * mData;
};
Function data_p will be used to access the actual data from the derived classes.
Lets create a detachable shared object class. Detachable shared object class detaches itself from the underlying pointer data if required.
template <typename T > class RDetachableRSharedObject: RSharedObject{ protected: T & data_p() { this->detach(); return RSharedObject ::data_p(); } const T & data_p() const { return RSharedObject ::data_p(); } };
Then smart pointer class
We will create a base class for smart pointer so that we can have smart pointer class for both object and array.
This smart pointer base class will derive from our RSharedObject class.
template <typename A, typename D >
class RSmartPointerBase: public RSharedObject < A >
{
public:
RSmartPointerBase(D * p)
{
this->data_p().mPtr = p;
this->data_p().mOwn = true;
}
bool isNull() const
{
return data() == 0;
}
D * data()
{
return this->data_p().mPtr;
}
const D * data() const
{
return this->data_p().mPtr;
}
D * take()
{
this->data_p().mOwn = false;
return this->data_p().mPtr;
}
D * operator->()
{
return data();
}
const D * operator->() const
{
return data();
}
D & operator*()
{
return *(data());
}
const D * operator*() const
{
return *(data());
}
};
Lets now create the actual smart pointer,
template < typename D >
class RSmartPointerData
{
public:
RSmartPointerData()
: mOwn(true),
mPtr(0)
{}
~RSmartPointerData()
{
if (mOwn) {
delete mPtr;
}
}
private:
RSmartPointerData(RSmartPointerData const &);
RSmartPointerData & operator=(RSmartPointerData const &);
public:
bool mOwn;
D * mPtr;
};
template < typename D >
class RSmartPointer: public RSmartPointerBase<RSmartPointerData<D>, D>
{
public:
RSmartPointer(D * p=0)
: RSmartPointerBase, D>(p)
{}
operator D*()
{
return this->data();
}
operator const D*() const
{
return this->data();
}
};
Lets now create the actual smart array pointer,
template < typename D >
class SmartArrayPointerData
{
public:
SmartArrayPointerData()
: mOwn(true),
mPtr(0)
{}
~SmartArrayPointerData()
{
if (mOwn) {
delete [] mPtr;
}
}
private:
SmartArrayPointerData(SmartArrayPointerData const &);
SmartArrayPointerData & operator=(SmartArrayPointerData const &);
public:
bool mOwn;
D * mPtr;
};
template <typename D >
class SmartArrayPointer: public RSmartPointerBase< SmartArrayPointerData<D>, D>
{
public:
SmartArrayPointer(D * p=0)
: RSmartPointerBase, D>(p)
{}
operator D*()
{
return this->data();
}
operator const D*() const
{
return this->data();
}
};
I know it is more code and less document, but hopefully it helps.
Complete implementation can be found at https://github.com/trsquarelab/glexamples/blob/master/src/common/rsmart_pointer.h
Great! Shared with my devs! thanks. Another question - is dataroom services your sphere of interest? Should I await for some reviews on this topic? Thanks in advance
ReplyDelete