Listing 4
// a simple reference counted UN-smart pointer
#ifndef NDEBUG
template<typename T>
struct counted_ptr {
counted_ptr(const new_ptr<T>& x) : mp(x.m), ref_count(new int(1)) {
}
counted_ptr() : mp(NULL), ref_count(NULL) {
}
bool operator==(const counted_ptr& x) const {
return mp == x.mp;
}
bool operator!=(const counted_ptr& x) const {
return mp != x.mp;
}
~counted_ptr() {
Release();
}
counted_ptr(const counted_ptr& x) {
private_assign(x);
}
T* operator->() const {
assert(mp != NULL);
return mp;
}
T& operator*() const {
assert(mp != NULL);
return *mp;
}
operator const ptr<T, !deletable>&() {
// only allows conversion to non-deletable pointers
return mp;
}
void operator=(const counted_ptr& x) {
if (*this == x) return; // change nothing
Release();
private_assign(x);
}
void Release() {
if (mp == NULL) return;
assert(ref_count != NULL && "implementation error");
--(*ref_count);
assert(*ref_count > 0 && "orphaning memory");
mp = NULL;
}
void Delete() {
if (mp == NULL) {
assert(ref_count == NULL && "implementation error");
return;
}
assert(ref_count != NULL && "implementation error");
assert(*ref_count == 1 && "can not delete when other
references still remain");
delete ref_count;
delete mp;
mp = NULL;
}
static counted_ptr Null() {
return counted_ptr();
}
private:
void private_assign(const counted_ptr& x) {
// private, because it is unsafe. The public methods
// make sure everything is kosher
mp = x.mp;
ref_count = x.ref_count;
if (mp != NULL) {
assert(ref_count != NULL && "implementation error");
++(*ref_count);
} else {
assert(ref_count == NULL && "implementation error");
}
}
private:
T* mp;
int* ref_count;
};
#else
template<typename T>
struct counted_ptr {
counted_ptr(const new_ptr<T>& x) : mp(x.m) {
}
counted_ptr() : mp(NULL){
}
bool operator==(const counted_ptr& x) const {
return mp == x.mp;
}
bool operator!=(const counted_ptr& x) const {
return mp != x.mp;
}
counted_ptr(const counted_ptr& x) {
mp = x.mp;
}
T* operator->() const {
return mp;
}
T& operator*() const {
return *mp;
}
operator const ptr<T, !deletable>&() {
return mp;
}
void operator=(const counted_ptr& x) {
mp = x.mp;
}
void release() {
mp = NULL;
}
void Delete() {
delete mp;
mp = NULL;
}
static counted_ptr null() {
return counted_ptr();
}
};
#endif