Преимущество передачи по значению

117
11 сентября 2019, 18:00

Отрывок из C++ Core Guidelines:

F.16: For “in” parameters, pass cheaply-copied types by value and others by reference to const

Reason. Both let the caller know that a function will not modify the argument, and both allow initialization by rvalues.

What is “cheap to copy” depends on the machine architecture, but two or three words (doubles, pointers, references) are usually best passed by value.

Возьмем к примеру x64 архитектуру. Размер слова и указателя равен 8 байтам.

Почему лучше передавать объект размера 2-3 слов (16-24 байт) по значению?

Ведь "лучше" передать по ссылке.

C++ Core Guidelines

Answer 1

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

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

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

По эти причинам (а также принимая во внимание move semantics и return value optimizations) можно существенно расширить диапазон случаев, когда лучше передавать даже существенно боле тяжелые объекты по значению.

Answer 2

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

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

Answer 3

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

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

Answer 4

Похоже, Вы неправильно поняли английский. По значению, а не ссылке на константу, обычно всегда передаются два-три приведённых варианта: double (приведён как самый большой интегрированный тип, меньшие само-собой), указатели и ссылки, занимающие в x64 одно слово.

READ ALSO
Clion и cmake:изменить (добавить) переменную окружения перед запуском приложения

Clion и cmake:изменить (добавить) переменную окружения перед запуском приложения

Имеется приложение, которое выводит содержимое переменной окружения:path

98
Redis VS hash map для C++?

Redis VS hash map для C++?

В общем, нашел интересную статью на хабре: https://habrcom/ru/company/mailru/blog/323242/

116
Не могу вызвать метод из контроллера

Не могу вызвать метод из контроллера

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

150