Каковы некоторые недостатки использования ссылки вместо указателя? - PullRequest
6 голосов
/ 10 ноября 2011

Данный класс «А» существует и является правильным. Каковы могут быть некоторые отрицательные результаты использования ссылки на «A» вместо указателя в классе «B». То есть:

// In Declaration File
class A;

class B
{
public:
   B();
   ~B();
private:
    A& a;
};

// In Definition File
B::B(): a(* new A())
{}

B::~B()
{
    delete &a;
}

Пропущен дополнительный код для дальнейшей корректности "B", такой как конструктор копирования и оператор присваивания, просто хотел продемонстрировать концепцию вопроса.

Ответы [ 6 ]

4 голосов
/ 10 ноября 2011

Непосредственные ограничения таковы:

  • Вы не можете изменить значение ссылки. Вы можете изменить A, к которому он относится, но вы не можете перераспределить или переназначить a в течение жизни B.
  • a никогда не должно быть 0.

Таким образом:

  • Объект не может быть назначен.
  • B не может быть копируемым, если только вы не научите A и его подтипы правильно клонировать.
  • B не будет хорошим кандидатом в качестве элемента типов коллекций, если хранится как значение. Вектор B s, скорее всего, будет проще всего реализован как std::vector<B*>, что может привести к дополнительным сложностям (или упрощениям, в зависимости от вашего дизайна).

Это могут быть хорошие вещи, в зависимости от ваших потребностей.

Предостережения:

  • нарезка - это еще одна проблема, о которой следует знать , если a назначается и назначение доступно в B.
2 голосов
/ 10 ноября 2011

Вы не можете изменить объект, на который ссылается символ после, например, при назначении.Кроме того, это делает ваш тип не POD (данный тип в любом случае будет не POD из-за закрытого члена данных, но в некоторых случаях это может иметь значение).запутать читателей вашего кода.

1 голос
/ 10 ноября 2011

Если вы используете ссылку:

  • Вы должны предоставить значение во время строительства
  • Вы не можете изменить то, к чему оно относится
  • Оно не может быть нулевым
  • Это предотвратит назначение вашего класса

Возможно, вы могли бы вместо этого использовать какой-нибудь умный указатель (std :: unique_ptr, std :: shared_ptr и т. Д.).Это дает дополнительное преимущество автоматического удаления объекта для вас.

1 голос
/ 10 ноября 2011

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

Я не думаю, что есть отрицательные результаты, кроме того факта, что delete &a может выглядеть странно.Тот факт, что объект был создан с помощью new, несколько теряется при привязке результата к ссылке, и это может иметь значение только потому, что неясен тот факт, что его временем жизни должно управлять B.

0 голосов
/ 21 января 2019

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

0 голосов
/ 10 ноября 2011

Ссылка на динамически размещенный объект нарушает принцип наименьшего удивления; то есть никто обычно не ожидает код, написанный как у вас. В целом, это увеличит стоимость обслуживания в будущем.

...