Передача объектов или передача указателей / указателей? - PullRequest
2 голосов
/ 27 февраля 2012

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

Мне любопытно, в чем разница с точки зрения хорошей практики / менее склонной к разрушению, когда речь идет о передаче объекта или указателя на этот объект?

Ответы [ 6 ]

8 голосов
/ 27 февраля 2012

Привыкайте проходить объекты по ссылке.

void DoStuff(const vector<int>& values)

Если вам нужно изменить исходный объект, опустите квалификатор const.

void DoStuff(vector<int>& values)

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

void DoStuff(vector<int>* values)

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

void DoStuff(vector<int> values)

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

1 голос
/ 27 февраля 2012

Передайте указатель на объект, если вы хотите иметь возможность указать небытие (передав NULL).

Старайтесь не передавать значения по объектам, так как это вызывает конструктор копирования для создания локальной версии объекта в рамках функции вызова. Вместо этого перейдите по ссылке. Однако здесь есть два режима. Чтобы получить точно такое же эффективное поведение передачи по значению (неизменяемая «копия») без издержек, передайте по ссылке const. Если вы чувствуете, что вам нужно изменить переданный объект, передайте (неконстантную) ссылку.

1 голос
/ 27 февраля 2012

Я выбираю const ссылку по умолчанию.Конечно, не - const, если вы должны мутировать объект для клиента.Отклонение от использования ссылок редко требуется.

Указатели не очень похожи на C ++, поскольку ссылки доступны.Ссылки хороши тем, что на них запрещено ссылаться ни на что. Обновление: Чтобы уточнить, предпочтительны правильные контейнеры для типов и массивов, но для некоторых внутренних реализаций вам нужно будет передать указатель.

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

void method(const std::string& str) {
  std::string myCopy(str);
  ...
0 голосов
/ 27 февраля 2012

Объектно-ориентированное программирование - это полиморфизм, принцип подстановки Лискова, старый код, вызывающий новый код. Передайте конкретный (производный) объект подпрограмме, которая работает с более абстрактными (базовыми) объектами. Если вы этого не делаете, вы не делаете ООП.

Это возможно только при передаче ссылок или указателей. Передача по значению лучше всего резервируется для значений.

Полезно различать значения и объекты. Ценности всегда конкретны, полиморфизма нет. Они часто неизменны. 5 - это 5, а «abc» - это «abc». Вы можете передать их по значению или по (const) ссылке.

Объекты всегда в некоторой степени абстрактны. Учитывая объект, почти всегда можно усовершенствовать его до более конкретного объекта. RectangularArea может быть Drawable, которое может быть Window, которое может быть ToplevelWindow, которое может быть ManagedWindow, которое может быть ... Эти должны быть переданы по ссылке.

Указатели - это совершенно отдельная банка червей. По моему опыту, лучше избегать голых указателей. Используйте умный указатель , который не может быть NULL . Если вам нужен необязательный аргумент, используйте явный шаблон класса optional, например boost::optional.

0 голосов
/ 27 февраля 2012

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

Первое, что вы можете сделать, - это то, должна ли вещь, которую вы передаете, изменить в вашем методе или нет.Если вы не собираетесь изменять его, тогда ссылка на const, вероятно, лучшая альтернатива (не меняя, я также имею в виду, что вы не намереваетесь вызывать какие-либо неконстантные методы этого объекта).Каковы преимущества этого?Вы экономите время для составления объекта, а также сама подпись метода скажет: «Я не буду изменять этот параметр».

Если вам нужно изменить этот объект, вы можете передать на него либо ссылку, либо указатель.Не обязательно выбирать только один из этих вариантов, чтобы вы могли выбрать любой из них.Единственное различие, о котором я могу думать, состоит в том, что указатель может быть НЕДЕЙСТВИТЕЛЕН (то есть вообще не указывает на какой-либо объект), в то время как ссылка всегда указывает на существующий объект.

Если то, что вам нужно в вашем методе, является копиейвашего объекта, то, что вы должны передать копию объекта (не ссылка и не указатель).Например, если ваш метод выглядит как

void Foo(const A& a) {
  A temp = a;
}

, то это явный признак того, что передача копии - лучшая альтернатива.

Надеюсь, это немного прояснит ситуацию.

0 голосов
/ 27 февраля 2012

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

Если вы хотите изменить объект, передайте ссылку на него.Если вы хотите защитить его от изменений внутри функции, передайте его по значению или по крайней мере по константной ссылке.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...