C/C++

Передача параметров в функцию по адресу.

Понятно, что крупные объекты, например массивы - лучше передавать по адресу, а не по значению. Однако не всегда по адресу передают крупные объекты. Меня интересует вот этот второй случай. Почему может быть более эффективной передача по адресу?
Крупные структуры передаются по значению в следующих случаях:
  1. Некомпетентность программиста (учившегося на Паскале и т.п. горе-языках). Самая частая причина.
  2. Если параметр только входной, и в любом случае нужна отдельная копия структуры. Меньше кода писать вручную. Правда, этот подход не работает, если копия нужна после возврата из функции.

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

А маленькие структуры могли и сейчас могут передаваться целиком в регистрах, например, в x87 до 8 вещественных чисел - через регистры FPU, а в Risc архитектурах вообще навалом именованных регистров. Собственно, их и в линейке x86, начиная с Pentium Pro, было уже штук 40, а в современных моделях - по полторы-две сотни, но они недоступны по именам, и потому параметры в них передать не получится. Некоторые трюкачи с конца 1990-х задействовали для передачи массивов и структур 128-битные регистры XMM (для Pentium MMX, Pentium II, ...), это позволяло передать до килобайта данных.

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

В общем, единственный способ надёжно определить, что происходит при передаче структуры по значению, - это смотреть ассемблерный листинг. А единственный способ получить достоверные данные о производительности - это профилирование.
ЭЖ
Эламан Жунузалы Уулу
54 053
Лучший ответ
Таиржан Тохтиев Я о другом спрашиваю: почему когда мы передаём небольшие объёмы данных, может быть эффективнее передавать входные параметры - по адресу?
Ну тут все очевидно. Упорядоченная память в виде стека будет работать многократно быстрее так как ей не нужно итерироваться через список адресов чтобы получить нужный. Можно обратиться к элементам по индексу и под капотом этого обращения будет сразу же изъятие данных. Передача по значению это копирование объекта и это минус как по времени так и по ресурсам. Ведь при передача адреса - передается только ссылка без создания объекта. Вот и получается что легковестные структуры переданные по зн могут оказаться в 10 раз быстрее, но стоит добавить в нее доп параметиы и методы и этот выигрыш будет сокращаться. Плата за такой выигрыш будет в вечном контроое за параметрами. Из за мелочной оптимизации. Лучше передавать все по ссылке и не думать о том что там у тебя...
Евгений Ширшев
Евгений Ширшев
10 755
Таиржан Тохтиев От меня трубуют обосновать почему передача отдельных переменных по адресу иногда более выгодна, чем передача отдельных переменных по значению.
То есть когда речь о небольших объёмах данных.