Многие ответы касаются того, как хранится счетчик ссылок (он хранится в общей памяти для всех shared_ptr, которые содержат один и тот же внутренний указатель), но большинство уклоняются от проблемы утечек.
Самый простой способ утечки памяти со ссылкой подсчитанными указателями - создание циклов. В качестве примера гарантируется, что не будет удален двойной список, в котором все указатели shared_ptr с по меньшей мере двумя элементами. Даже если внешние указатели освобождаются, внутренние указатели будут по-прежнему считаться, а счетчик ссылок не достигнет 0. Это, по крайней мере, самая наивная реализация.
Простейшим решением проблемы цикла является смешивание shared_ptr (ссылки с подсчитанными указателями) со слабыми указателями, которые не разделяют права собственности на объект.
Общие указатели будут делиться как ресурсом (указателем), так и дополнительной информацией reference_count. Когда вы используете слабые указатели, счетчик ссылок удваивается: есть подсчет ссылок общего указателя и подсчет ссылок на слабые указатели. Ресурс выдается всякий раз, когда общий счетчик указателей достигает 0, но информация reference_count остается в живых до тех пор, пока не будет освобожден последний слабый указатель.
В двусвязном списке внешняя ссылка хранится в shared_ptr, а внутренние ссылки - только weak_ptr. Всякий раз, когда нет внешних ссылок (shared_ptr), элементы списка освобождаются, удаляя слабые ссылки. В конце все слабые ссылки были удалены, и последний слабый указатель на каждый ресурс освобождает информацию reference_count.
Это менее запутанно, чем кажется вышеприведенный текст ... Я попробую еще раз.
Это самый правильный ответ. –
Метод связанных списков позволяет избежать дополнительного распределения, но очень сложно сделать «потокобезопасным» без глобального мьютекса. («поточно-безопасный», как в «как потокобезопасный, как необработанный указатель») – curiousguy
Также, если вы используете 'make_shared', он также может избежать дополнительного распределения, помещая выделенный объект и счетчик экземпляров в один блок памяти. – Ferruccio