Подтвердить что ты не робот

Как работает счетчик ссылок на подсчет ссылок?

Другими словами, как реализация отслеживает счет?

Существует ли поддерживаемый map-объект объект, доступный для всех экземпляров shared_ptr, чей ключ является адресом указателя и значением является количество ссылок? Если я должен реализовать shared_ptr, это первая идея, которая приходит мне на ум.

Есть ли возможность утечки памяти в случае этих интеллектуальных указателей с подсчетом ссылок? Если да, то как я могу их избежать?

4b9b3361

Ответ 1

Я видел два разных неинтрузивных подхода к этому:

  • Умный указатель выделяет небольшой блок памяти для контрольный счетчик. Каждая копия умный указатель затем получает указатель на фактический объект и указатель на счетчик ссылок.
  • В дополнение к указателю на объект, каждый умный указатель содержит предыдущий и следующий указатель, тем самым образуя двусвязный список умные указатели на конкретный объект. Счетчик ссылок неявный в списке. Когда умный указатель скопирован, он добавляет себя список. При уничтожении каждый умный указатель удаляется из список. Если он последний в список затем освобождает ссылочный объект также.

Если вы перейдете здесь и прокрутите к нижней части, есть отличная диаграмма, которая объясняет эти методы гораздо более четко.

Ответ 2

Каждый объект интеллектуального указателя содержит общий счетчик ссылок - по одному для каждого необработанного указателя.

Вы можете взглянуть на эту статью. Эта реализация сохраняет их в отдельном объекте, который копируется вокруг. Вы также можете взглянуть на повысить документацию или взглянуть на Статья в Википедии о умных указателях.

Ответ 3

Нет. shared_ptr просто сохранит один дополнительный указатель для подсчета ссылок.

Когда вы делаете копию объекта shared_ptr, скопируйте указатель со списком ссылок, увеличьте его и скопируйте указатель на содержащийся объект.

Ответ 4

Создание утечки памяти с помощью интеллектуальных указателей с подсчетом ссылок очень просто. Просто создайте любую графоподобную структуру объектов, которая имеет цикл на графике. Объекты цикла будут препятствовать освобождению друг друга. Это невозможно решить автоматически - например, при создании списка с двойной связью вы должны заботиться о том, чтобы никогда не удалять более одного объекта за раз.

Ответ 5

Насколько я помню, была проблема указателя подсчета ссылок, рассмотренного в главе "Эффективный С++".

В принципе, у вас есть класс "светлый" указатель, содержащий указатель на класс, содержащий ссылку, которая знает, что нужно для увеличения/уменьшения ссылки и уничтожения объекта-указателя. Этот класс подсчета ссылок указывает на объект, на который нужно ссылаться.

Ответ 6

Многие ответы касаются того, как хранится счетчик ссылок (он хранится в общей памяти для всех shared_ptr, которые содержат один и тот же внутренний указатель), но большинство из них избегают проблемы утечек.

Самый простой способ утечки памяти со ссылками подсчитанных указателей - создание циклов. В качестве примера гарантируется, что не будет удален двойной список, в котором все указатели shared_ptr с по меньшей мере двумя элементами. Даже если внешние указатели освобождаются, внутренние указатели все равно будут подсчитываться, а счетчик ссылок не достигнет 0. Это, по крайней мере, самая наивная реализация.

Простейшим решением проблемы цикла является смешивание shared_ptr (ссылки с подсчитанными указателями) со слабыми указателями, которые не разделяют права собственности на объект.

Общие указатели будут делиться как ресурсом (указателем), так и дополнительной информацией reference_count. Когда вы используете слабые указатели, счетчик ссылок удваивается: есть подсчет ссылок общего указателя и подсчет ссылок на слабые указатели. Ресурс выделяется всякий раз, когда общий счетчик указателей достигает 0, но информация reference_count остается живой до тех пор, пока не будет освобожден последний слабый указатель.

В двусвязном списке внешняя ссылка хранится в shared_ptr, а внутренние ссылки - только weak_ptr. Всякий раз, когда нет внешних ссылок (shared_ptr), элементы списка освобождаются, удаляя слабые ссылки. В конце все слабые ссылки были удалены, и последний слабый указатель на каждый ресурс освобождает информацию reference_count.

Он менее запутан, чем кажется выше. Повторюсь позже.