Step 4 (S-11163)

From Stepik Wiki
Jump to: navigation, search

Step on Stepik: https://stepik.org/lesson/4650/step/4

Для ScopedPtr мы запретили копирование, однако, копирование можно и разрешить. Это позволит реализовать более продвинутый умный указатель — SharedPtr. Он отличается от ScopedPtr тем, что кроме хранения указателя на объект, он хранит еще и счетчик ссылок (количество объектов SharedPtr, которые хранят один и тот же указатель).

Имея такой счетчик, мы можем определить момент, когда на объект, выделенный в куче, не останется больше ссылок (когда счетчик ссылок станет равным 0), и освободить память.

Поддержка счетчика ссылок состоит из нескольких частей:


  • в конструкторе SharedPtr от ненулевого указателя мы инициализируем счетчик ссылок в 1 (конструктор создает первый SharedPtr, который хранит указатель),
  • в конструкторе копирования мы увеличиваем счетчик ссылок на 1, если копируемый SharedPtr содержит ненулевой указатель (конструктор копирования создает еще один SharedPtr с указателем на тот же самый объект),
  • в деструкторе мы уменьшаем значение счетчика на 1, если в объекте SharedPtr хранится ненулевой указатель (мы удаляем один SharedPtr, который указывает на объект в куче),
  • оператор присваивания уменьшает счетчик ссылок левого операнда на 1, если внутри левого SharedPtr хранится ненулевой указатель, увеличивает счетчик правого SharedPtr на 1, если в правом SharedPtr хранится ненулевой указатель (обычное дело для оператора присваивания — сначала освобождаем старые ресурсы, потом выделяем новые, но при этом нужно быть особенно внимательным с присваиванием самому себе).

Для класса SharedPtr могут оказаться полезными следующие методы (кроме операторов * и ->, конструктора копирования, оператора присваивания, деструктора и конструктора):

  • метод get, как и в случае со ScopedPtr,
  • метод reset — аналогичен reset у ScopedPtr, но освобождает память, только если счетчик ссылок после декремента равен 0.