Почему бы вам не использовать ссылки на умные указатели? - PullRequest
24 голосов
/ 07 октября 2008

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

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

Ответы [ 6 ]

14 голосов
/ 07 октября 2008

Если вы говорите о shared_ptr здесь ...

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

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

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

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

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

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

5 голосов
/ 07 октября 2008

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

3 голосов
/ 07 октября 2008

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

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

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

1 голос
/ 07 октября 2008

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

По сути, ссылка на умный указатель - это тупой указатель со всеми рисками и недостатками, которые влечет за собой последний.

0 голосов
/ 01 октября 2013

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

const smart_ptr<T>&

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

Возвращение ссылки на смарт-указатель из функции вызывает все виды проблем.

0 голосов
/ 07 октября 2008

У нас есть смартпоинтеры, изготовленные на заказ, и мы всегда стремимся передавать «const refsomething &»

он не увеличивает или уменьшает интеллектуальный указатель, и поэтому - и что более важно - избегаются вызовы InterLockedIncrement / Decrement, что, в свою очередь, устраняет ограничение памяти и все, что с этим связано : блокировка шины, аннулирование кэша, ...

...