Язык C++ был разработан с учётом специфики системного программирования, поэтому не имеет встроенного сборщика мусора. Но порой требуется передать куда-то указатель и не заботиться о его дальнейшей судьбе. Для этих целей существует такое понятие, как «Умные указатели».
Концепция заключается в том, что Вы пишите класс-обёртку для указателей и определяете в нём необходимые операторы. В деструкторе этого класса следует высвободить память, которую занимает указатель. Для того, что бы не удалить указатель раньше времени, принято считать количество ссылок на объект. Для этого объявляем счётчик-переменную в куче и в операторе присвоения и копирующем конструкторе инкрементируем его, а в деструкторе — декрементируем. Как только счётчик в деструкторе достигает нуля — высвобождаем всю занятую память. Следующий пример демонстрирует концепцию создания класса «умного» указателя.

#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.