Концепция заключается в том, что Вы пишите класс-обёртку для указателей и определяете в нём необходимые операторы. В деструкторе этого класса следует высвободить память, которую занимает указатель. Для того, что бы не удалить указатель раньше времени, принято считать количество ссылок на объект. Для этого объявляем счётчик-переменную в куче и в операторе присвоения и копирующем конструкторе инкрементируем его, а в деструкторе - декрементируем. Как только счётчик в деструкторе достигает нуля - высвобождаем всю занятую память. Следующий пример демонстрирует концепцию создания класса "умного" указателя.
#ifndef SMARTPTR_H
#define SMARTPTR_H
namespace SmartPtr {
template<typename TypeT>
class CSmartPtr
{
public:
explicit CSmartPtr(TypeT * ptr = NULL)
{
mp_pointer = ptr;
mp_link_counter = new int;
*mp_link_counter = 1;
}
CSmartPtr(const CSmartPtr<TypeT> & rhs)
{
mp_pointer = rhs.mp_pointer;
mp_link_counter = rhs.mp_link_counter;
(*mp_link_counter)++;
}
~CSmartPtr()
{
Release();
}
CSmartPtr<TypeT> & operator = (const CSmartPtr & rhs)
{
if(&rhs != this)
{
Release();
mp_pointer = rhs.mp_pointer;
mp_link_counter = rhs.mp_link_counter;
(*mp_link_counter)++;
}
return *this;
}
TypeT * operator -> ()
{
return mp_pointer;
}
TypeT operator * ()
{
return *mp_pointer;
}
TypeT * GetPointer()
{
return mp_pointer;
}
private:
void Release()
{
if(! --(*mp_link_counter))
{
delete mp_link_counter;
mp_link_counter = NULL;
if(mp_pointer)
{
delete mp_pointer;
mp_pointer = NULL;
}
}
}
private:
TypeT * mp_pointer;
int * mp_link_counter;
};
} // namespace SmartPtr
#endif // SMARTPTR_H
Приведу небольшой пример, использующий этот класс.
#include <iostream>
#include "SmartPtr.h"
class CTest
{
public:
~CTest()
{
std::cout << "destructorn";
}
void print() const
{
std::cout << "i'm testn";
}
};
void funct(SmartPtr::CSmartPtr<CTest> test)
{
test->print();
}
int main()
{
SmartPtr::CSmartPtr<CTest> test(new CTest);
funct(test);
return 0;
}
Вывод программы, как и ожидалось, будет таким
i'm test
destructor
В некоторых реализациях я встречал определение оператора приведения типа. Так как приведение типов в C++ не приветствуется, то и я не стал определять этот оператор. В случае крайней нужды можно воспользоваться методом GetPointer.