Как осуществляется подсчет ссылок?
Реализацию интеллектуального указателя можно деконструировать, используя дизайн класса на основе политик 1 , в:
Политика хранения
Право собственности
Политика конвертации
Политика проверки
включено в качестве параметров шаблона.
Популярные стратегии владения включают: глубокое копирование, подсчет ссылок, связывание ссылок и деструктивное копирование.
Подсчет ссылок отслеживает количество умных указателей, указывающих (владеющих 2 ) на один и тот же объект. Когда число обращается в ноль, объект pointee удаляется 3 . Фактический счетчик может быть:
- Разделяется между объектами интеллектуального указателя, где каждый интеллектуальный указатель содержит указатель на счетчик ссылок:
- Включено только в дополнительную структуру, которая добавляет дополнительный уровень косвенности объекту pointee. Здесь затраты на хранение счетчика в каждом интеллектуальном указателе обмениваются с более низкой скоростью доступа:
Содержится в самом объекте pointee: навязчивый подсчет ссылок. Недостатком является то, что объект должен быть построен априори с возможностями для подсчета:
Наконец, метод в вашем вопросе, подсчет ссылок с использованием двусвязных списков, называется связыванием ссылок, и это:
... [1] полагается на то, что вам на самом деле не нужно фактическое количество объектов интеллектуальных указателей, указывающих на один объект-указатель; вам нужно только определить, когда это количество уменьшается до нуля. Это приводит к идее ведения «списка владельцев»:
Преимущество связывания ссылок перед подсчетом ссылок состоит в том, что первое не использует дополнительное свободное хранилище, что делает его более надежным: создание интеллектуального указателя со ссылками не может завершиться с ошибкой. Недостатком является
эта ссылочная ссылка требует больше памяти для ведения бухгалтерии (три указателя против только одного указателя плюс одно целое число). Кроме того, подсчет ссылок должен быть немного быстрее - когда вы копируете умные указатели, требуется только косвенное указание и приращение. Управление списком немного сложнее. В заключение,
Вы должны использовать ссылки ссылки только тогда, когда в свободном магазине мало. В противном случае предпочитайте подсчет ссылок.
Относительно вашего второго вопроса:
Использует ли он (std::shared_ptr
) двусвязный список?
Все, что я мог найти в стандарте C ++, было:
20.7.2.2.6 создание shared_ptr
...
7. [Примечание: Эти функции обычно выделяют больше памяти, чем sizeof(T)
, чтобы учесть внутренние структуры бухгалтерского учета, такие как счетчик ссылок. —Конечная записка]
Что, на мой взгляд, исключает двусвязные списки, поскольку они не содержат фактического количества.
Ваш третий вопрос:
Есть ли подводные камни для использования std::shared_ptr
?
Управление ссылками, считая или связывая, является жертвой утечки ресурса, известной как циклическая ссылка . Давайте возьмем объект A, который содержит интеллектуальный указатель на объект B. Кроме того, объект B содержит интеллектуальный указатель на A. Эти два объекта образуют циклическую ссылку; даже если вы их больше не используете, они используют друг друга. Стратегия управления ссылками не может обнаружить такие циклические ссылки, и эти два объекта остаются распределенными навсегда.
Поскольку реализация shared_ptr
использует подсчет ссылок, циклические ссылки потенциально являются проблемой.Циклическую цепочку shared_ptr
можно разорвать, изменив код так, чтобы одна из ссылок была weak_ptr
.Это делается путем назначения значений между общими указателями и слабыми указателями, но слабый указатель не влияет на счетчик ссылок.Если единственные указатели, которые указывают на объект, являются слабыми, объект уничтожается.
1.Каждая конструктивная особенность с несколькими реализациями, если сформулирована как политика.
2.Умные указатели, аналогичные указателям, указывающим на объект, выделенный с помощью new
, не только указывают на этот объект, но и несут ответственность за его уничтожение и освобождение занимаемой памяти.
3.Без дальнейших проблем, если никакие другие необработанные указатели не используются и / или не указывают на это.
[1] Современный дизайн C ++: применяются общие шаблоны программирования и проектирования.Андрей Александреску, 1 февраля 2001 г.