使用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编译器(理论上)是否总能确定函数内是否更改了函数参数?
简答:不
答案很长,不,有证据。
在我使用clang编译的MacBook pro上,我运行了几次测试,看到没有实际时间差异:
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; }
产量
添加了4875711个刻度 鳕鱼拿了4885519个蜱虫
然而,这些时间确实应该花费一些时间,因为clock
不是最精确的定时function,并且可能受到其他运行程序的影响。
所以,这里是生成的比较汇编:
_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,写入内存将触发运行时exception。
– 杰米