volchek/smart_pointer
Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
Простая реализация шаблонного умного указателя smart_ptr на основе подсчета ссылок. Класс реализует основную функциональность, предоставляемую указателем std::shared_ptr. Для подсчета ссылок используется внутренняя структура с полем counter (хранит текущее количество ссылок на захваченный указатель), и два метода, отвечающих за инкремент и декремент значения в поле counter. Не подходит для хранения указателя на массив, так как память высвобождается с помощью оператора delete. Отдельные методы выбрасывают исключение типа std::logic_error. В классе smart_ptr реализованы следующие методы: 1. Конструкторы 1) конструктор без параметров – создает пустой умный указатель 2) конструктор с одним параметром типа std::nullptr_t – создает пустой указатель из переданного nullptr 3) explicit-конструктор с одним параметром типа "сырого" указателя – создает умный указатель, передавая ему во владение объект, на который указывает "сырой" указатель 4) конструктор копирования Создает новый умный указатель, который разделяет владение тем же объектом, что и умный указатель, переданный в качестве аргумента. Счетчик ссылок инкрементируется. 5) конструктор перемещения Создает новый умный указатель, передавая ему во владение объект, которым владеет умный указатель-аргумент. Счетчик ссылок не увеличивается. Умный указатель, переданный в качестве аргумента, остается в корректном состоянии (становится пустым указателем). 2. Операторы присваивания 1) копирующее = Позволяет изменить объект, которым владеет умный указатель. Умный указатель, переданный в качестве аргумента, сохраняет владение своим объектом. Рассматриваются три случая: а) Если умный указатель был пуст, то он просто принимает во владение новый объект; счетчик ссылок инкрементируется. б) Если умный указатель был единственным владельцем некоторого объекта (внутренний счетчик ссылок равен 1), то память, занимаемая хранимым объектом, освобождается, после чего умный указатель принимает во владение новый объект и инкрементируется счетчик ссылок. в) Если умный указатель был не единственным владельцем некоторого объекта (внутренний счетчик ссылок превышает 1), то счетчик ссылок декрементируется. После этого умный указатель принимает во владение новый объект; счетчик ссылок инкрементируется. 2) перемещающее = Позволяет изменить объект, которым владеет умный указатель. Умный указатель, переданный в качестве аргумента, теряет владение своем объектом, но остается в корректном (зануленном) состоянии. Учитываются те же три случая, что и в случае с копирующим оператором присваивания. 3. Деструктор Высвобождает память через вызов оператора delete, когда количество ссылок становится равным нулю. В остальных случаях уменьшает счетчик ссылок на единицу, если указатель не пуст. 4. Операторы и методы, разыменовывающие указатель или обеспечивающие доступ к членам объекта 1) get – возвращает "сырой" указатель, который владеет smart_ptr. 2) операторы operator* и operator-> – обеспечивают доступ к полям и методам объекта. Если smart_ptr владеет указателем на простой тип вроде int, char и т.д., то operator* позволяет получить значение, которое хранится по "сырому" указателю. Если smart_ptr пуст, генерируется исключение типа std::logic_error. 5. Вспомогательные методы 1) empty – проверяет, владеет ли умный указатель каким-нибудь объектом 2) use_count – возвращает количество ссылок на объект, находящийся во владении умного указателя 3) swap – обменивает значения двух умных указателей; корректно работает при обмене с пустым указателем На простых тестах удалось добиться поведения, почти аналогичного тому, которое демонстрирует указатель std::shared_ptr (для компилятора gcc7.1). Отличия оказались связаны с генерацией исключений в операторе * .