Когда передавать по значению? - PullRequest
2 голосов
/ 09 июня 2010

Дорогие все. Мне было интересно, есть ли примеры ситуаций, когда вы намеренно передавали бы аргумент по значению в C. Позвольте мне перефразировать. Когда вы целенаправленно используете передачу C по значению для больших объектов? Или когда вас волнует, что аргумент объекта полностью скопирован в локальную переменную?

РЕДАКТИРОВАТЬ : Теперь, когда я думаю об этом, если вы можете избежать указателей, тогда сделайте. В настоящее время «глубокое» копирование возможно в большинстве случаев в небольших приложениях, а мелкое копирование более подвержено ошибкам указателя. Может быть.

Ответы [ 7 ]

3 голосов
/ 09 июня 2010

В C (без ссылок) вы передаете по значению по 3 причинам.

  • Вы не хотите, чтобы источник изменялся принимающей функцией вне контекста. Это (было) стандартная причина, которой учат в школе, а именно, почему передавать по значению.

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

  • Передача по значению занимает меньше времени. Слабая причина, чтобы быть уверенным, но это так.

Ключевое слово const отрицает большую часть причины 1, но причина 2 все еще имеет свои достоинства и является основной причиной, по которой я передаю значение.

1 голос
/ 09 июня 2010

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

В любом случае, зачем передавать весь объект вместо указателя на объект?Ну, во-первых, ваш компилятор может иметь возможность оптимизировать вызов таким образом, что под крышками копируется только адрес.Также / В качестве альтернативы, после того, как вы введете указатели, ваш компилятор может не выполнить такую ​​оптимизацию вашей функции из-за псевдонимов.Это также менее подвержено ошибкам, поэтому не нужно помнить о разыменовании.Вызывающий также может быть уверен, что то, что он передал, не изменено (const на самом деле не гарантирует этого, его можно - опасно - выбросить)

1 голос
/ 09 июня 2010

Я следую как правило:

  • передаем встроенные типы по значению (int, char, double, float ...)
  • передаем классы и структуры по (const) ссылка.Обработка указателей вообще не требуется.

Никогда не было проблем с таким способом работы.

1 голос
/ 09 июня 2010

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

1 голос
/ 09 июня 2010

Ну, во-первых, если вы хотите изменить его.

Представьте себе следующую надуманную функцию:

int getNextCharAndCount (char *pCh);

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

Мне трудно найти другой вариант использования, в котором указатель потребовался бы, если бы вы только хотели использовать (но не изменить) базовый символ. Это не значит, что никого не существует, конечно: -)

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

То, что вы имеете в виду, это передача по значению и передача по ссылке.

0 голосов
/ 09 июня 2010

В зависимости от того, как построен стек вызовов, char и char * могут занимать одинаковое количество места.Как правило, лучше выровнять значения по границам слов.Стоимость доступа к 32-битному указателю на границе слова может быть значительно ниже, чем к нему без границы слова.

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

CONST int ONE = 1;
increment( *ONE );
print ONE;

Вывод равен 2, если константа была изменена.

0 голосов
/ 09 июня 2010

Я не думаю, что ваш аргумент о символах держит воду.Даже если ваш char концептуально равен 1 байту, каждый аргумент вызова функции обычно преобразуется в целый (размером с слово) регистр и в такое же количество места в стеке для эффективности.

Вы можете передатьцелое struct в стеке в качестве аргумента, если вы действительно хотите (и, я считаю, также вернуть их).Это способ избежать как выделения памяти, так и необходимости беспокоиться о гигиене указателей.

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