138 lines
3.7 KiB
C++
138 lines
3.7 KiB
C++
![]() |
#ifndef __MRW__SMARTPOINTER_HPP__
|
||
|
#define __MRW__SMARTPOINTER_HPP__
|
||
|
|
||
|
namespace mrw {
|
||
|
|
||
|
class PointerCounter {
|
||
|
private:
|
||
|
unsigned int _cnt;
|
||
|
public:
|
||
|
PointerCounter():
|
||
|
_cnt(1) {
|
||
|
}
|
||
|
PointerCounter* incr() {
|
||
|
++_cnt;
|
||
|
return this;
|
||
|
}
|
||
|
int decr() {
|
||
|
return --_cnt;
|
||
|
}
|
||
|
int get() {
|
||
|
return _cnt;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class SmartPointerParent {
|
||
|
protected:
|
||
|
template<class TYPE>
|
||
|
PointerCounter* getCounter(TYPE& sp) {
|
||
|
return sp._cnt;
|
||
|
}
|
||
|
template<class TYPE>
|
||
|
typename TYPE::Pointer getPointer(TYPE& sp) {
|
||
|
return sp._ptr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/** @addtogroup AutoTools */
|
||
|
//@{
|
||
|
|
||
|
/** @brief Smart Pointer Implementation
|
||
|
@pre #include <mrw/smartpointer.hpp>
|
||
|
|
||
|
This is a smart pointer that can be casted withing the
|
||
|
inheritance of the pointer it is storing.
|
||
|
|
||
|
A smart pointer is a pointer that is automatically cleaned up
|
||
|
when it is no more referenced. Therefore you only allocate
|
||
|
memory, but you never free it, just as in Java, cleaning up is
|
||
|
done behind the scenes. If you assign a smart pointer to another
|
||
|
smart pointer, both point to the same memory. A counter counts
|
||
|
the number of references to the object and frees it as soon as
|
||
|
the last smart pointer pointing to the same memory has been
|
||
|
destroyed.
|
||
|
|
||
|
A smart pointer is used just as a normal pointer, except that
|
||
|
you can assign it only to other smart pointers, not to ordinary
|
||
|
pointers, and you don't have to delete the memory allocated. Any
|
||
|
memory assigned to a smart pointer is consumed and mustn't be
|
||
|
used any more. Never allocate a smart pointer with
|
||
|
<code>new</code>, but only the pointer that is stored in the
|
||
|
smart pointer!
|
||
|
|
||
|
@note memory assigned to a smart pointer is consumed
|
||
|
*/
|
||
|
template<class TYPE> class SmartPointer: public SmartPointerParent {
|
||
|
private:
|
||
|
typedef TYPE* Pointer;
|
||
|
PointerCounter* _cnt;
|
||
|
TYPE* _ptr;
|
||
|
private:
|
||
|
void drop() {
|
||
|
if (_cnt && !_cnt->decr()) {
|
||
|
delete _cnt; _cnt=0;
|
||
|
delete _ptr; _ptr=0;
|
||
|
}
|
||
|
}
|
||
|
private:
|
||
|
friend class SmartPointerParent;
|
||
|
friend class SmartPointerTest;
|
||
|
public:
|
||
|
SmartPointer():
|
||
|
_cnt(0), _ptr(0) {
|
||
|
}
|
||
|
SmartPointer(const SmartPointer<TYPE>& o):
|
||
|
_cnt(o._cnt?o._cnt->incr():0), _ptr(o._ptr) {
|
||
|
}
|
||
|
SmartPointer(TYPE* ptr):
|
||
|
_cnt(ptr ? new PointerCounter : 0), _ptr(ptr) {
|
||
|
}
|
||
|
template<class OTHER> SmartPointer(const SmartPointer<OTHER>& o):
|
||
|
_cnt(0), _ptr(dynamic_cast<TYPE*>(getPointer(o))) {
|
||
|
if (_ptr) _cnt = getCounter(o)->incr();
|
||
|
}
|
||
|
~SmartPointer() {
|
||
|
drop();
|
||
|
}
|
||
|
SmartPointer& operator=(const SmartPointer<TYPE>& o) {
|
||
|
if (o._ptr==_ptr) return *this;
|
||
|
drop();
|
||
|
_cnt = o._cnt ? o._cnt->incr() : 0;
|
||
|
_ptr = o._ptr;
|
||
|
return *this;
|
||
|
}
|
||
|
SmartPointer& operator=(TYPE* ptr) {
|
||
|
if (ptr==_ptr) return *this;
|
||
|
drop();
|
||
|
_cnt = ptr ? new PointerCounter : 0;
|
||
|
_ptr = ptr;
|
||
|
return *this;
|
||
|
}
|
||
|
template<class OTHER>
|
||
|
SmartPointer& operator=(const SmartPointer<OTHER>& o) {
|
||
|
if (getPointer(o)==_ptr) return *this;
|
||
|
drop();
|
||
|
_ptr = dynamic_cast<TYPE*>(getPointer(o));
|
||
|
_cnt = _ptr ? getCounter(o)->incr() : 0;
|
||
|
return *this;
|
||
|
}
|
||
|
TYPE& operator*() {
|
||
|
return *_ptr;
|
||
|
}
|
||
|
const TYPE& operator*() const {
|
||
|
return *_ptr;
|
||
|
}
|
||
|
TYPE* const operator->() {
|
||
|
return _ptr;
|
||
|
}
|
||
|
const TYPE* const operator->() const {
|
||
|
return _ptr;
|
||
|
}
|
||
|
operator bool() {
|
||
|
return _ptr!=0;
|
||
|
}
|
||
|
};
|
||
|
//@}
|
||
|
}
|
||
|
#endif
|