23

例如,考虑:

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编译器(理论上)是否可以始终确定函数内部是否更改了函数参数?

4

4 回答 4

17

简短的回答:没有

长答案,不,有证据。

我在使用 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 滴答
cadd 占用了 4885519 个刻度

然而,这些时间确实应该持保留态度,因为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只是对调用者的提示,参数不会被更改,并且在像上面描述的简单场景中,不会导致编译任何不同的程序集。

于 2012-09-06T01:15:37.533 回答
9

答案可能取决于您的编译器、优化级别以及编译器是否决定内联函数。如果您对这些东西感到好奇,只需查看编译器生成的实际程序集并找出答案就很容易了。

于 2012-09-06T00:54:43.267 回答
0

不,他们两个应该是相同的速度。出于您的原因,假设它将原始值传递给 sum 函数,那么 sum 函数中的某些代码如何修改原始值,例如另一个线程。

一般来说,const 对参数的性能没有影响。如果 const 是局部/全局变量,它确实会影响性能,因为某些计算可以像 const 一样移至编译时间。

于 2012-09-06T00:59:27.680 回答
0

虽然晚了,但编译器可以将定义为 const 的变量放在只读内存段/块中,这样如果试图通过一些愚蠢的指针写入地址,写入内存将触发运行时异常。

——杰米

于 2017-03-31T20:23:26.580 回答