template <class Type>
class SharedPtr {
private:
Type* ptr_;
int* count;
public:
// Инициализируем счетчик ссылок в 1
// (конструктор создает первый SharedPtr, который хранит указатель)
explicit SharedPtr(Type *ptr = 0) {
if (ptr != 0) count = new int(1);
ptr_ = ptr;
}
// В деструкторе мы уменьшаем значение счетчика на 1,
// если в объекте SharedPtr хранится ненулевой указатель
// (мы удаляем один SharedPtr, который указывает на объект в куче)
~SharedPtr() {
if (ptr_ != 0) {
(*count)--;
if (*count == 0) {
delete ptr_;
delete count;
}
}
}
// В конструкторе копирования мы увеличиваем счетчик ссылок на 1,
// если копируемый SharedPtr содержит ненулевой указатель
// (конструктор копирования создает еще один SharedPtr с указателем на тот же самый объект)
SharedPtr(const SharedPtr &ptr) {
if (ptr.ptr_ != 0) {
(*(ptr.count))++;
count = ptr.count;
}
ptr_ = ptr.ptr_;
}
// Оператор присваивания уменьшает счетчик ссылок левого операнда на 1,
// если внутри левого SharedPtr хранится ненулевой указатель,
// увеличивает счетчик правого SharedPtr на 1,
// если в правом SharedPtr хранится ненулевой указатель
// (обычное дело для оператора присваивания — сначала освобождаем старые ресурсы,
// потом выделяем новые,
// но при этом нужно быть особенно внимательным с присваиванием самому себе).
SharedPtr& operator=(const SharedPtr &ptr) {
if (this != &ptr) {
if (ptr_ != 0) {
(*count)--;
if (*(count) == 0) {
delete ptr_;
delete count;
}
}
if (ptr.ptr_ != 0) {
(*(ptr.count))++;
count = ptr.count;
}
ptr_ = ptr.ptr_;
}
return *this;
}
// Освобождаем старый указатель, и захватываем новый
void reset(Type *ptr = 0) {
if (ptr_ != 0) {
(*count)--;
if (*(count) == 0) {
delete ptr_;
delete count;
}
}
ptr_ = ptr;
if (ptr_ != 0) count = new int(1);
}
// Возвращает указатель, сохраненный внутри Shared
// (например, чтобы передать его в какую-то функцию)
Type* get() const {
return ptr_;
}
Type& operator*() const {
return *ptr_;
}
Type* operator->() const {
return ptr_;
}
};
Comments
0 B
|👍
/👎