Это упрощенный пример, иллюстрирующий вопрос:
class A {};
class B
{
B(A& a) : a(a) {}
A& a;
};
class C
{
C() : b(a) {}
A a;
B b;
};
Итак, B отвечает за обновление части C. Я запустил код через lint, и он пожаловался на элемент ссылки: lint # 1725 . Здесь говорится о заботе о копировании и присваиваниях по умолчанию, что достаточно справедливо, но копирование и присваивание по умолчанию также плохо работают с указателями, поэтому здесь мало преимуществ.
Я всегда стараюсь использовать ссылки там, где это возможно, поскольку голые указатели неуверенно определяют, кто несет ответственность за удаление этого указателя. Я предпочитаю встраивать объекты по значению, но если мне нужен указатель, я использую auto_ptr в данных-членах класса, которому принадлежит указатель, и передаю объект в качестве ссылки.
Обычно я бы использовал указатель в данных члена только тогда, когда указатель мог быть нулевым или мог измениться. Есть ли другие причины предпочесть указатели ссылкам на элементы данных?
Верно ли сказать, что объект, содержащий ссылку, не должен быть назначен, поскольку ссылка не должна изменяться после инициализации?
источник
Ответы:
Избегайте ссылочных членов, потому что они ограничивают то, что может делать реализация класса (включая, как вы упомянули, предотвращение реализации оператора присваивания), и не дают никаких преимуществ по сравнению с тем, что может предоставить класс.
Примеры проблем:
до C ++ 0x, в любом случаередактировать: C ++ теперь имеет делегирующие конструкторы ).
оператор и т. Д.), Но ведет себя как указатель (может болтаться) - поэтому, например, в Google Style Guide это не рекомендуется.источник
Мое практическое правило:
источник
Объекты редко должны разрешать присваивание и другие вещи, такие как сравнение. Если рассматривать какую-то бизнес-модель с такими объектами, как «Отдел», «Сотрудник», «Директор», трудно представить себе случай, когда один сотрудник будет закреплен за другим.
Поэтому для бизнес-объектов очень хорошо описывать отношения «один-к-одному» и «один-ко-многим» как ссылки, а не указатели.
И, вероятно, нормально описывать отношение «один или ноль» как указатель.
Так что никакого фактора «мы не можем назначить».
Многие программисты просто привыкли к указателям, и поэтому они найдут любой аргумент, чтобы избежать использования ссылки.
Наличие указателя в качестве участника заставит вас или члена вашей команды проверять указатель снова и снова перед использованием с комментарием «на всякий случай». Если указатель может быть нулевым, то указатель, вероятно, используется как своего рода флаг, что плохо, поскольку каждый объект должен играть свою роль.
источник
Используйте ссылки, когда можете, и указатели, когда вам нужно.
источник
В некоторых важных случаях присваиваемость просто не требуется. Часто это легкие обертки алгоритмов, которые упрощают вычисления, не покидая области видимости. Такие объекты являются первыми кандидатами на роль ссылочных членов, поскольку вы можете быть уверены, что они всегда содержат действительную ссылку и никогда не нуждаются в копировании.
В таких случаях не забудьте сделать оператор присваивания (а часто и конструктор копирования) непригодным для использования (путем наследования
boost::noncopyable
или объявления их закрытыми).Однако, как уже прокомментировал пользователь pts, для большинства других объектов это не так. Здесь использование ссылочных элементов может быть огромной проблемой, и обычно этого следует избегать.
источник
Поскольку все, кажется, раздают общие правила, я предлагаю два:
Никогда и никогда не используйте ссылки в качестве членов класса. Я никогда не делал этого в своем собственном коде (кроме как для того, чтобы доказать себе, что я был прав в этом правиле), и не могу представить себе случай, когда я бы сделал это. Семантика слишком запутанная, и на самом деле ссылки были созданы не для этого.
Всегда, всегда используйте ссылки при передаче параметров функциям, кроме основных типов, или когда алгоритм требует копии.
Эти простые правила сослужили мне хорошую службу. Я оставляю правила использования умных указателей (но, пожалуйста, не auto_ptr) в качестве членов класса другим.
источник
Да для: Верно ли утверждение, что объект, содержащий ссылку, не должен быть назначен, поскольку ссылка не должна изменяться после инициализации?
Мои практические правила для членов данных:
источник
Да. Читаемость вашего кода. Указатель делает более очевидным, что член является ссылкой (по иронии судьбы :)), а не содержащимся в нем объектом, потому что, когда вы его используете, вам нужно отменить ссылку на него. Я знаю, что некоторые люди думают, что это старомодно, но я все же считаю, что это просто предотвращает путаницу и ошибки.
источник
Я не рекомендую использовать элементы ссылочных данных, потому что вы никогда не знаете, кто будет производным от вашего класса и что они могут захотеть сделать. Они могут не захотеть использовать объект, на который имеется ссылка, но, будучи ссылкой, вы вынудили их предоставить действительный объект. Я сделал это с собой достаточно, чтобы перестать использовать элементы справочных данных.
источник
Если я правильно понял вопрос ...
Ссылка как параметр функции вместо указателя: как вы указали, указатель не дает понять, кому принадлежит очистка / инициализация указателя. Предпочитайте общую точку, когда вам нужен указатель, он является частью C ++ 11, и weak_ptr, когда достоверность данных не гарантируется в течение всего времени существования класса, принимающего указанные данные .; также является частью C ++ 11. Использование ссылки в качестве параметра функции гарантирует, что ссылка не равна нулю. Чтобы обойти это, вам нужно изменить языковые функции, а нас не волнуют свободные кодеры.
Ссылка на переменную-член: как указано выше в отношении достоверности данных. Это гарантирует, что указанные данные, на которые затем делается ссылка, действительны.
Перенос ответственности за достоверность переменных на более раннюю точку кода не только очищает более поздний код (класс A в вашем примере), но также делает его понятным для человека, использующего.
В вашем примере, который немного сбивает с толку (я бы действительно попытался найти более четкую реализацию), A, используемый B, гарантирован на время жизни B, поскольку B является членом A, поэтому ссылка усиливает это и это (возможно) более понятно.
И на всякий случай (что маловероятно, поскольку это не имеет никакого смысла в контексте вашего кода), другая альтернатива, использовать параметр A без ссылки, без указателя, скопирует A и сделает парадигму бесполезной - I на самом деле не думаю, что вы имеете в виду это как альтернативу.
Кроме того, это также гарантирует, что вы не сможете изменить данные, на которые ссылаются, где можно изменить указатель. Константный указатель будет работать, только если ссылка / указатель на данные не изменяемы.
Указатели полезны, если параметр A для B не был гарантированно установлен или мог быть переназначен. А иногда слабый указатель слишком подробен для реализации, и многие люди либо не знают, что такое weak_ptr, либо просто не любят его.
Разорви, пожалуйста, этот ответ :)
источник