Ответ 1
Перейдите по значению - определенно. Если система 64-битная, это означает, что она быстро копирует 64-битное слово.
Это вопрос эффективности 64-битных int. Предполагая, что мне не нужно изменять значение параметра "int", следует передать его по значению или ссылке.
Предполагая 32-битную машину:
1) 32-разрядный int: Я думаю, что ответ "pass by value", поскольку "pass by reference" будет иметь накладные расходы на дополнительный поиск в памяти.
2) 64-битный int: если я передаю по ссылке, я передаю только 32-разрядный адрес в стеке, но нуждаюсь в дополнительном поиске в памяти. Итак, какой из них лучше (ссылка или значение)?
Что делать, если машина 64 бит?
С уважением,
В JP
Перейдите по значению - определенно. Если система 64-битная, это означает, что она быстро копирует 64-битное слово.
Даже на 64-битной машине пропуск по значению лучше (с некоторыми очень немногими исключениями), потому что он может быть передан как значение регистра.
Передайте их как boost::call_traits<int64_t>::param_type
. Этот шаблон отражает лучшие методы передачи любого типа на поддерживаемых платформах. Следовательно, это будет отличаться на 32 и 64 битных платформах, но вы можете использовать один и тот же код везде. Он даже работает внутри других шаблонов, где вы еще не знаете точного типа.
В целях аргумента давайте проигнорируем тривиальный случай устранения различий оптимизаторов. Предположим также, что вы используете Microsoft 64-разрядные соглашения о вызовах (которые отличаются от Linux ABI), тогда у вас есть 4 64-разрядных регистра для передачи таких значений, прежде чем вам придется прикладывать их к стеку. Это явно лучше.
Для 32-битного приложения по значению, и они попадут прямо в стек. Вместо ссылки вместо этого указывается указатель в регистре (опять же, до тех пор, пока не прибегают к стеку, разрешается использование нескольких таких регистров). Мы можем это сделать в некоторых выводах из g++ -O3 -S, вызывая f1 (99) по значению и f2 (101) по ссылке const:
void f1(int64_t);
void f2(const int64_t&);
int main()
{
f1(99);
f2(101);
}
...
pushl 0
pushl $99
call _Z2f1x // by value - pushed two halves to stack
leal -8(%ebp), %eax
movl %eax, (%esp)
movl $101, -8(%ebp)
movl $0, -4(%ebp)
call _Z2f2RKx // by const& - ugly isn't it!?!
Вызываемая функция затем должна быть извлечена перед первым использованием (если она есть). Вызываемая функция позволяет кэшировать значения, считанные в регистрах, так что требуется только один раз. При подходе к стеку значение может быть перечитано по желанию, поэтому регистр не должен быть зарезервирован для этого значения. При использовании указателя указатель или 64-битное значение, возможно, нужно будет сохранить где-то более предсказуемым (например, нажатым или другим менее полезным регистром), чтобы этот регистр необходимо было мгновенно освободить для какой-либо другой работы, но 64-разрядный параметр int потребуется позже. Все, трудно догадаться, что быстрее - может быть зависимо от CPU/register-usage/optimiser/etc, и это не стоит пытаться.
A node to pst advice...
"эффективность": (KISS) передайте его, как вы проходите каждое другое кровавое целое. - pst
... хотя иногда вы применяете KISS к параметрам шаблона и делаете их все const T & хотя некоторые могут поместиться в регистры....
Используйте немного здравого смысла,
если для объекта требуется сложный конструктор копирования, возможно, стоит перейти по ссылке (говоря, что - довольно много объектов boost предназначены для передачи по значению, а не для ссылки просто потому, что внутренняя реализация довольно тривиальная ) Есть один нечетный, который я на самом деле не разработал, std::string
, я всегда передаю это по ссылке...
Если вы намерены изменить переданное значение, используйте ссылку
Else, PASS-BY-VALUE!
У вас есть узкое место производительности с аргументами для функций? Кроме того, не тратьте слишком много времени на то, чтобы беспокоиться о том, что это лучший способ пройти...
Оптимизация, беспокоясь о том, как передается int
, похожа на pi ** ing в море...