Передача аргументов в функции с параметрами 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
выше различия, если они есть, должны быть минимальными.
Изменить: Пример sum
предназначен только для иллюстрации моей точки. Я не ожидаю, что в этом конкретном примере должны быть большие различия. Но мне интересно, может ли в более сложных ситуациях модификатор const
внутри параметра функции может быть использован компилятором, чтобы сделать функцию быстрее. Я сомневаюсь, что компилятор всегда может определить, изменяется ли параметр внутри функции (следовательно, мой второй вопрос ниже); поэтому я ожидаю, что когда он найдет модификатор const
, он сделает что-то другое, чем когда нет модификатора const
.
Вопрос: В общем случае функция будет быстрее, если ее аргументы const
, чем когда они не являются?
Вопрос 2: В целом, может ли компилятор C (теоретически) всегда определять, изменяется ли параметр функции внутри функции?
Ответы
Ответ 1
Короткий ответ: Нет
Длинный ответ, нет, с доказательством.
Я проверил этот тест несколько раз и не видел разницы в реальном времени, на моем 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
является лишь подсказкой для вызывающего, аргумент не будет изменен и в простом сценарии, подобном описанному выше, не приведет к компиляции любой другой сборки.
Ответ 2
Ответ, вероятно, зависит от вашего компилятора, уровня оптимизации и того, решает ли компилятор встроить функцию. Если вам интересно об этих вещах, легко просто взглянуть на фактическую сборку, созданную вашим компилятором, и узнать.
Ответ 3
Нет. обе они должны быть одинаковой скорости.
предположим, что он передает исходные значения в функцию sum, как насчет того, какой код из функции sum изменит исходное значение, например, другой поток.
В целом, const не влияет на производительность при аргументах. это влияет на производительность, если константа является локальной/глобальной переменной, потому что некоторые вычисления могут быть перенесены на компиляцию, как если бы она была константой.
Ответ 4
Поздно, компилятор мог помещать переменные, определенные как const, в сегмент/блок памяти только для чтения, так что если была сделана попытка записать на адрес, через некоторый топик указателя, запись в память приведет к возникновению исключения во время выполнения.
- Jamey