Почему использование ссылки или уникального указателя класса - это плохо?

В книге Херба Саттера и Андрея Александреску «Стандарты кодирования C ++. 101 правила, рекомендации и передовой опыт» в Правиле 52 заключительная цитата такова:

"В редких случаях классы, которые имеют члены странных типов (например, ссылки, std :: auto_ptrs), являются исключением, потому что они имеют особую семантику копирования. В классе, содержащем ссылку или auto_ptr, вам, вероятно, потребуется написать конструктор копирования и оператор присваивания, но деструктор по умолчанию уже работает правильно. (Обратите внимание, что использование элемента reference или auto_ptr почти всегда неверно.) "

Понятно, почему использование ссылок в качестве членов - не лучшая идея (ответ на этот вопрос находится в этом сообщении: Что лучше: указатели или ссылки в данных-членах?)

  1. Что касается современного C ++, означает ли это, что использование unique_ptr в качестве члена класса обычно плохо? Или это была проблема только с auto_ptr и отсутствием семантики перемещения?
  2. Следует ли тогда использовать shared_ptr для полиморфного поведения?

Заранее спасибо!


person Roman2452809    schedule 01.07.2019    source источник
comment
Поскольку unique_ptr не копируется, у него нет странной семантики копирования, в отличие от auto_ptr.   -  person Jarod42    schedule 01.07.2019
comment
Переход от совета по auto_ptr к выводам по unique_ptr - это большой скачок.   -  person StoryTeller - Unslander Monica    schedule 01.07.2019
comment
я думаю, что это следует читать как не используйте ссылочные элементы, если вам не нужно, чтобы они были ссылочными, вместо того, чтобы никогда не использовать ссылочные элементы, хотя я могу неправильно понять цитату, я также не согласен с другими вариантами использования фразы почти всегда   -  person 463035818_is_not_a_number    schedule 01.07.2019
comment
auto_ptr был уловкой и отражал наивное представление о том, как работает владение. Уроки, которые мы извлекли из этого, включены в новые типы общих указателей, поэтому рекомендации о том, как использовать auto_ptr, не применимы ни к чему другому. Да упокоится она с миром.   -  person Pete Becker    schedule 01.07.2019
comment
@PeteBecker Также ссылка на rvalue не существовала, когда был разработан auto_ptr, поэтому никто не может обвинять lib ppl в том, что у нее нет надлежащих инструментов ядра языка   -  person curiousguy    schedule 04.07.2019


Ответы (2)


  1. Что касается современного C ++, означает ли это, что использование unique_ptr в качестве члена класса обычно плохо?

Это не значит, что использование уникальных указателей - неплохая вещь.

Или это была проблема только с auto_ptr и отсутствием семантики перемещения?

Основная проблема заключается в том, что копирование auto_ptr передает право собственности на указанный ресурс. Это то, что автор называет «своеобразной семантикой копирования».

Учитывая, что const auto_ptr не может быть скопирован, он не так опасен, как неконстантный. У него было нишевое использование, но использование некопируемых типов довольно ограничено до C ++ 11.

Уникальный указатель не имеет особой семантики копирования. Фактически, уникальные указатели вообще не копируются. Это не такая большая проблема в C ++ 11, где тип может быть перемещаемым. Уникальные указатели охватывают все варианты использования, в которых auto_ptr можно было использовать, а также другие, где auto_ptr был коварным.

  1. Следует ли тогда использовать shared_ptr для полиморфного поведения?

Общий указатель можно использовать, но это не обязательно.

P.S. auto_ptr устарел в C ++ 11 и полностью удален из стандартной библиотеки в C ++ 17.

person eerorika    schedule 01.07.2019
comment
Копирование не const auto_ptr. Постоянные объекты (auto_ptr или содержащие их классы) не могут быть скопированы. Core C ++ официально поддерживает вызов функции, принимающей ссылку NON const на копию ctor. - person curiousguy; 04.07.2019

Использование члена unique_ptr - неплохая практика, поскольку класс, членом которого он является, является владельцем выделенного объекта. Однако это усложняет обработку содержащего его класса, поскольку предотвращает копирование этого класса. Итак, если класс содержит какие-либо другие нетривиальные члены, вам придется написать конструктор перемещения, оператор присваивания перемещения и деструктор для вашего класса.

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

person rashmatash    schedule 01.07.2019
comment
I'd consider using shared_ptr as class members a bad practice, since it doesn't imply any kind of ownership Напротив, общий указатель подразумевает совместное владение, как следует из названия. - person eerorika; 01.07.2019
comment
Согласованный! Я имел в виду, что никто конкретно не отвечает за управление временем жизни этого объекта, что мне не нравится в целом (но это также вопрос стиля и вкуса). - person rashmatash; 01.07.2019
comment
Что вы имеете в виду под недетерминированным? - person curiousguy; 04.07.2019
comment
@eerorika Что, черт возьми, такое совместное владение? Кому принадлежит ресурс? - person curiousguy; 04.07.2019
comment
@curiousguy Все общие указатели, указывающие на этот ресурс, совместно владеют друг другом. В уникальном владении владелец несет ответственность за высвобождение ресурса. При совместном владении потенциально может быть несколько владельцев, и последний уничтожаемый владелец отвечает за освобождение ресурса. - person eerorika; 04.07.2019
comment
@eerorika Итак, собственность разделена? Кому принадлежит ресурс? Как это владение? - person curiousguy; 04.07.2019
comment
@curiousguy So ownership is divided? Я бы использовал слово общий, но конечно. Who owns the resource? Набор общих указателей, указывающих на ресурс. How is that ownership? Я не совсем понимаю, о чем вы спрашиваете. Общие указатели являются владельцем, потому что они несут ответственность за выпуск, и наоборот. Это два способа выразить одну и ту же концепцию. - person eerorika; 04.07.2019
comment
@eerorika Юридическая концепция собственности означает, что вы можете использовать и уничтожить объект. Совместное владение подразумевает, что вы не знаете, какие виды использования допустимы (можете ли вы изменить значение? Как?), И что вы не можете его уничтожить. Кроме того, вы не можете передать собственное (не разделяемое) право собственности (нет release). Так что это вообще не собственность. - person curiousguy; 05.07.2019
comment
@curiousguy Где официально указана эта юридическая концепция собственности? Вы имеете в виду, что интеллектуальные указатели не реализуют семантику владения или что-то еще? (Я не совсем понимаю, о чем вы). Право собственности может быть передано от одного уникального указателя к другому или от уникального указателя к общему указателю. Вы не можете передать совместное владение обратно в уникальное владение. - person eerorika; 05.07.2019
comment
@eerorika Право собственности может быть наиболее изученной и понятной правовой концепцией. Совместное владение не является владением, поскольку оно не имеет необходимых свойств: владелец должен иметь возможность уничтожить принадлежащий ему ресурс или передать право собственности; ни то, ни другое не поддерживается. shared_ptr не моделирует право собственности, а моделирует контракт о сохранении активности до (из-за отсутствия лучшего срока). - person curiousguy; 05.07.2019
comment
@curiousguy Ownership may be the most studied and well understood legal concept. Прошу цитату. an owner should be able to destroy the owned resource, or transfer the ownership Это свойства уникального владения. Действительно, общий указатель не имеет уникальной семантики владения. Совместное владение отличается от уникального владения. (for lack of better term) Для этого есть термин, используемый, например, в стандарте C ++: это называется совместное владение. AFAIK, это довольно устоявшийся термин. - person eerorika; 05.07.2019
comment
@eerorika И это плохой термин и без прецедента IMO. Совместное владение просто противоречием. У него нет атрибутов того, что люди обычно называют владением: если вы совладелец, вам ничего не принадлежит. У вас есть только договор с единственным владельцем (блок управления), что ресурс не уйдет слишком рано. Вы можете согласиться с условиями владения по такому контракту, но я не согласен. Вы даже не можете знать, являетесь ли вы единственным владельцем, с (очень плохим) решением бросить unique() вместо того, чтобы его исправить! - person curiousguy; 05.07.2019