Передача аргументов функциям с параметрами const: это быстрее?
рассмотрим, к примеру:
int sum(int a, int b)
{
return a + b;
}
и
int sum(const int a, const int b)
{
return a + b;
}
второй подход в целом быстрее?
параметры функции в C копируются и отправляются функции, так что изменения внутри функции не влияют на исходные значения. Мое рассуждение заключается в том, что во втором sum
выше, компилятор точно знает, что a
и b
не изменяются внутри функции, поэтому она может просто передавать исходные значения без их копирования первый. Вот почему я думаю, что второй sum
быстрее, чем первый. Но я точно не знаю. В конкретном простом примере sum
выше, различия, если таковые имеются, должны быть минимальными.
Edit: на sum
пример просто иллюстрирует мою точку зрения. Я не ожидаю, что в этом конкретном примере должны быть большие различия. Но интересно, если в более сложных ситуациях const
модификатор внутри параметра функции может быть использован компилятор, чтобы сделать функцию быстрее. Я сомневаюсь, что компилятор всегда может определить, изменяется ли параметр внутри функции (отсюда мой 2-й вопрос ниже); поэтому я ожидаю, что когда он найдет const
модификатор, он делает что-то другое, чем когда нет const
модификатор.
вопрос: в общем случае функция будет быстрее, когда ее аргументы const
, чем, когда их нет?
Вопрос 2: в общем, может Компилятор C (теоретически) всегда определяет, изменяется ли параметр функции внутри функции?
4 ответов
короткий ответ:
долгий ответ, нет, с доказательством.
я провел этот тест, пару раз, и не видел никакой разницы в реальном времени, на моем MacBook pro, скомпилированном с clang:
int add(int a, int b)
{
return a + b;
}
const int cadd(const int a, const int b)
{
return a + b;
}
int main (int argc, char * argv[])
{
#define ITERS 1000000000
clock_t start = clock();
int j = 0;
for (int i = 0; i < ITERS; i++)
{
j += add(i, i + 1);
}
printf("add took %li ticks\n", clock() - start);
start = clock();
j = 0;
for (int i = 0; i < ITERS; i++)
{
j += cadd(i, i + 1);
}
printf("cadd took %li ticks\n", clock() - start);
return 0;
}
выход
add took 4875711 ticks cadd took 4885519 ticks
эти времена действительно следует принимать с солью, однако, как clock
не является наиболее точным из функций синхронизации и может зависеть от других запущенных программ.
вот сравненная сборка генерируется:
_add:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl -4(%rbp), %esi
addl -8(%rbp), %esi
movl %esi, %eax
popq %rbp
ret
_cadd:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl -4(%rbp), %esi
addl -8(%rbp), %esi
movl %esi, %eax
popq %rb
Итак, как вы можете видеть, есть без разницы между двумя. Передача аргумента как const
- это только подсказка вызывающему данный довод не будут изменены, а по простому сценарию, как описано выше, не приведет ни к какому другому скомпилированную сборку.
ответ, вероятно, зависит от вашего компилятора, уровня оптимизации и того, решит ли компилятор встроить функцию. Если вам интересно об этих вещах, легко просто посмотреть на фактическую сборку, созданную вашим компилятором, и узнать.
нет. оба должны двигаться с одинаковой скоростью. по вашей причине предположим, что он передает исходные значения в функцию sum, как насчет некоторого кода из функции sum изменить исходное значение, например, другой поток.
В общем случае const не влияет на производительность при аргументах. это влияет на производительность, если const является локальной / глобальной переменной, потому что некоторые вычисления можно переместить во время компиляции, как если бы это была const.
хотя и поздно для партии, компилятор может поместить переменные, определенные как const, в сегмент/блок памяти только для чтения, так что если была предпринята попытка записать на адрес, с помощью некоторого указателя tomfoolery, запись в память вызовет исключение во время выполнения.
-- Джейми