The idea behind this is mainly educational but I might even consider using it in reality if turns out to be good. Here's my first try at implementing smart pointers:
template<typename T>
class smart_pointer{
T* pointer;
std::size_t *refs;
void clear(){
if (!--*refs){
delete pointer;
delete refs;
}
}
public:
smart_pointer(T* p = NULL)
: pointer(p), refs(new std::size_t(1))
{}
smart_pointer(const smart_pointer<T>& other)
: pointer(other.pointer), refs(other.refs)
{
++*refs;
}
~smart_pointer(){
clear();
}
smart_pointer<T>& operator=(const smart_pointer<T>& other){
if (this != &other){
clear();
pointer = other.pointer;
refs = other.refs;
++*refs;
}
return *this;
}
smart_pointer<T>& operator=(T* p){
if (pointer != p){
pointer = p;
*refs = 1;
}
return *this;
}
T& operator*(){
return *pointer;
}
const T& operator*() const{
return *pointer;
}
T* operator->(){
return pointer;
}
const T* operator->() const{
return pointer;
}
std::size_t getCounts(){
return *refs;
}
};
I have tested this under valrind and its clean. Also, to see how much the "smartness" makes things slower, I did the following test:
struct foo{
int a;
};
template<typename pointer_t>
class bar{
pointer_t f_;
public:
bar(foo *f)
:f_(f)
{}
void set(int a){
f_->a = a;
}
};
int main()
{
foo *f = new foo;
typedef smart_pointer<foo> ptr_t;
// typedef boost::shared_ptr<foo> ptr_t;
// typedef foo* ptr_t;
bar<ptr_t> b(f);
for (unsigned int i = 0; i<300000000; ++i)
b.set(i);
// delete f;
return 0;
}
Here is some timing between my implementation, boost, and raw pointers: (code compiled with clang++ -O3
)
typedef smart_pointer<foo> ptr_t;
real 0m0.006s
user 0m0.001s
sys 0m0.002s
typedef boost::shared_ptr<foo> ptr_t;
real 0m0.336s
user 0m0.332s
sys 0m0.002s
typedef foo* ptr_t;
real 0m0.006s
user 0m0.002s
sys 0m0.003s
My implementation seems to be running almost as fast as raw pointers, which I think is a good sign. What worries me here is why Boost is running slower. Have I missed something in my implementation that is important and I might get into trouble for later?