В этом репозитори собраны мои реализации умных указателей в C++
Также для реализации UniquePtr
был написан класс CompressedPair для более умного хранения объекта делитера внутри UniquePtr
.
Тесты для указателей находятся в папке tests.
В файле main.cpp приведен пример использования умных указателей для реализации дву-связного списка. Запустить код можно с помощью команды:
clang++ main.cpp -std=c++20 -o main && ./main
IntrusivePtr
-- умный указатель, похожий по семантике на SharedPtr
, без возможности брать WeakPtr
на указатель.
Реализация данного класса намного проще, чем SharedPtr
.
Это достигается за счет ограничения на пользовательский тип. Он должен удовлетворять следующему условию:
- Внутри типа находится счетчик ссылок (поэтому указатель интрузивный: счетчик находится прямо в объекте).
- Есть метод
IncRef()
, уменьшающий внутренний счетчик ссылок - Есть метод
DecRef()
, уменьшающий внутренний счетчик ссылок; при достижении нуля объект автоматически разрушается. - Есть метод
RefCount()
, возвращающий текущее значения счетчика.
Важно, что все состояние указателя находится в объекте, на который он указывает. Это позволяет создавать корректный IntrusivePtr
из сырого указателя, ровно как с enable_shared_from_this
.
Рядом с IntrusivePtr
реализован удобный класс-миксин, позволяющий вставить счетчик ссылок в любой объект, просто отнаследовавшись от него:
class MyClazzWithIntrusiveCounter : public SimpleRefCounted<MyStringWithIntrusiveCounter> {
...
};
За счет более строгих требований на пользовательский тип, чем у SharedPtr
, и отсутствия WeakPtr
IntrusivePtr
реализуется намного проще и эффективнее.
Удобная абстракция со внешним счетчиком ссылок позволяет легко использовать IntrusivePtr
для нетривиальных времен жизни (например ObjectPool
в тестах).
Большую часть использований std::shared_ptr
в вашем коде на самом деле можно заменить на более легковесный IntrusivePtr
.