Параметры функции: Копия или указатель?

Я новичок в C++ и у меня есть вопросы, это один из них.

Есть ли ЛЮБАЯ причина, когда вы используете функцию, которая принимает один или несколько параметров, параметры которых, как вы знаете, всегда будут храниться в переменной перед вызовом функции, чтобы передать копию переменной, а не указатель на переменную ?

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
9
0
9 937
6

Ответы 6

ссылка более распространена, или ссылка на константу, если они не собираются меняться.

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

int * ohoh = новый int; удалить охох; cout << ohoh; // ненулевой нулевой указатель

MattyT 04.11.2008 14:52

вот почему я не тестирую нулевые указатели (если не указано, что функция может возвращать null). Нулевой указатель - это очень небольшое подмножество глобальной проблемы "недопустимого указателя". Почему бы нам не проверить, например, что 1 будет явно недействительным как 0 (за некоторыми исключениями, где также действителен 0) ...

Ilya 04.11.2008 16:26

Главный вопрос не в производительности, а в семантике и в том, изменяет ли ваша функция данные в структуре.

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

Если ваша функция не изменяет структуру, то нет причин копировать значения, поскольку они будут только прочитаны.

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

Что касается производительности, то копирование структуры требует больше усилий, но это довольно второстепенно. В первую очередь помните о семантике кода.

Избегайте использования указателя. Используйте постоянную ссылку, если параметр IN, иначе просто ссылку для параметра IN OUT

Есть несколько способов, которыми передача копии может быть дешевле, чем передача указателя.

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

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

А теперь часть ответа, которую вы, вероятно, не хотите слышать: обычно это не имеет большого значения! Используйте метод передачи параметров, наиболее подходящий для семантики вашей программы. Если позже вы обнаружите, что существует узкое место в производительности в определенной области, сосредоточьтесь на повышении производительности в этой области. Не переусердствуйте с оптимизацией!

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

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

void value_semantics(my_obj obj);
void value_semantics(const my_obj& obj);

Однако метод константной ссылки также имеет некоторые недостатки, он предотвращает несколько оптимизаций, которые компилятор может сделать из-за проблемы с псевдонимом, а также для объектов с тривиальными конструкторами дополнительный уровень косвенности (ссылка реализована как указатель) может перевесить преимущества избежания копировать.

Чтобы получить семантику ссылок, вы можете выбрать передачу по ссылке или по указателю, поскольку другие уже сказали ссылки более естественны, чем указатели в C++ (вам не нужно использовать адрес оператора &) и единственное реальное преимущество указателей если вы хотите включить значения NULL.

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

Другие вопросы по теме