2008-10-07 3 views
24

Я помню, где-то читал, что использование ссылок на интеллектуальные указатели может привести к повреждению памяти. Это просто из-за использования ссылки умного указателя после его уничтожения? Или происходит подсчет ссылок?Почему вы не должны использовать ссылки на интеллектуальные указатели?

Спасибо за разъяснение

+0

Это та же самая причина, по которой хранение ссылок на другие типы объектов является плохим, объект может быть уничтожен, и у вас будет обвисшая ссылка. Умные указатели должны удерживать объект, который они указывают на живые, но мы не говорим об объекте с указателем на объект, мы говорим о самом объекте интеллектуального указателя. – bames53 2011-10-26 16:59:25

+0

См. Http://stackoverflow.com/questions/327573/c-passing-references-to-boostshared-ptr – 2014-09-18 17:33:02

ответ

14

Предполагая, что вы говорите о shared_ptr здесь ...

Является ли это просто из-за использования ссылки смарт-указатель после его была уничтожена?

Это хороший ответ. Вы можете не знать абсолютно время жизни указателя, на который ссылается ваша ссылка.

Чтобы обойти это, вам нужно посмотреть в boost :: weak_ptr. Он не участвует в подсчете ссылок. Когда вам нужно использовать его, он дает вам shared_ptr, который уходит после вашего завершения. Он также сообщит вам, когда будет собрано ссылка на указатель.

Из weak_ptr документации

Шаблона магазинов класса weak_ptr «слабая ссылки» на объект, который уже управляемый shared_ptr. К доступ к объекту, weak_ptr может быть преобразован в shared_ptr, используя конструктор shared_ptr или элемент блокировка функции. Когда последний shared_ptr на объект уходит и объект удаляется, попытка получить shared_ptr из weak_ptr экземпляров, относящихся к удаляемым объекту не получится: конструктор будет сгенерирует исключение типа импульса :: bad_weak_ptr и weak_ptr :: lock вернет пустой shared_ptr.

Обратите внимание, что метод expired() также сообщит вам, находится ли ваш ptr по-прежнему.

5

При использовании интеллектуальных указателей (или любого объекта управления распределением) вы рассчитываете на поведение, определенное в конструкторе/деструкторе, для управления refs/derefs/locks/unlocks. В результате эти типы объектов должны быть истинными объектами для правильной работы. при использовании ссылок на такие объекты (или указатели) вы обходите механизм (и запрашиваете клинг).

3

Есть еще много случаев, когда ссылка на интеллектуальный указатель - хорошая идея. Очевидным примером является метод присваивания класса интеллектуального указателя, который принимает ссылку другому интеллектуальному указателю в качестве его параметра.

Создание метода, который принимает ссылку на интеллектуальный указатель, означает, что этот параметр не увеличивает счетчик внутренних ссылок интеллектуального указателя. Это может повысить производительность - но, вероятно, не так много. Кроме того, есть много вещей, которые метод не может сделать со ссылкой - или оригинальным умным указателем. Если вы знаете, что это такое и избегают их, то переключение по ссылке работает просто отлично. Разумеется, цель умных указателей - не знать об этих вещах.

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

1

«Умная» часть интеллектуальных указателей управляется конструкторами, деструкторами, операторами-ассистентами и другими функциями класса интеллектуальных указателей. Используя ссылку, вы обходите эти операции - конструктор не будет вызван, когда ваша ссылка будет инициализирована, и деструктор не будет вызван, когда ваша ссылка выходит за рамки.

В сущности, ссылка на интеллектуальный указатель является немым указателем со всеми рисками и ошибками, которые влечет за собой последний.

+0

«с учетом всех рисков и ошибок, которые последний влечет за собой.»? – curiousguy 2011-11-23 03:00:25

0

Мы заказ smartpointers и мы всегда делаем привычку пропусканием «константный refsomething &»

не увеличивать или уменьшать смарт-указатель, и как таковой - и что более важно - вызовы InterlockedIncrement/Уменьшение исключается, что в поворотах позволяет избежать memory fence и всех вещей, которые идут с этим: блокировка шины, недействительность кэша, ...

0

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

const smart_ptr<T>& 

Интересно и полезно, сопзЬ мешает вам использовать ссылку, чтобы сказать, нулевому смарт-указателю и удалить объект, но он не останавливает первоначальный интеллектуальный указатель от обнуления, и ваша ссылка будет отражать это изменение.

Возвращая ссылку на интеллектуальный указатель от функции, запрашивает всевозможные проблемы.

Смежные вопросы