Skip to content

Latest commit

 

History

History
40 lines (32 loc) · 3.4 KB

readme.md

File metadata and controls

40 lines (32 loc) · 3.4 KB

Smart Pointers

В этом репозитори собраны мои реализации умных указателей в C++

Также для реализации UniquePtr был написан класс CompressedPair для более умного хранения объекта делитера внутри UniquePtr.

Тесты для указателей находятся в папке tests.

Usage

В файле main.cpp приведен пример использования умных указателей для реализации дву-связного списка. Запустить код можно с помощью команды:

clang++ main.cpp -std=c++20 -o main && ./main

IntrusivePtr

IntrusivePtr -- умный указатель, похожий по семантике на SharedPtr, без возможности брать WeakPtr на указатель. Реализация данного класса намного проще, чем SharedPtr. Это достигается за счет ограничения на пользовательский тип. Он должен удовлетворять следующему условию:

  1. Внутри типа находится счетчик ссылок (поэтому указатель интрузивный: счетчик находится прямо в объекте).
  2. Есть метод IncRef(), уменьшающий внутренний счетчик ссылок
  3. Есть метод DecRef(), уменьшающий внутренний счетчик ссылок; при достижении нуля объект автоматически разрушается.
  4. Есть метод RefCount(), возвращающий текущее значения счетчика.

Важно, что все состояние указателя находится в объекте, на который он указывает. Это позволяет создавать корректный IntrusivePtr из сырого указателя, ровно как с enable_shared_from_this.

Рядом с IntrusivePtr реализован удобный класс-миксин, позволяющий вставить счетчик ссылок в любой объект, просто отнаследовавшись от него:

class MyClazzWithIntrusiveCounter : public SimpleRefCounted<MyStringWithIntrusiveCounter> {
    ...
};

Зачем он нужен?

За счет более строгих требований на пользовательский тип, чем у SharedPtr, и отсутствия WeakPtr IntrusivePtr реализуется намного проще и эффективнее. Удобная абстракция со внешним счетчиком ссылок позволяет легко использовать IntrusivePtr для нетривиальных времен жизни (например ObjectPool в тестах). Большую часть использований std::shared_ptr в вашем коде на самом деле можно заменить на более легковесный IntrusivePtr.