为什么 const int 比 const int& 快?

Why is const int faster than const int&?

本文关键字:int const 为什么      更新时间:2023-10-16

有一天我无意中注意到了这一点,现在决定对它进行广泛的测试。

所以,当我调用一个函数时:

#define Type int
#define Prm const Type &
Type testfunc1(Prm v1, Prm v2, Prm v3, Prm v4, Prm v5, Prm v6, Prm v7, Prm v8, Prm v9, Prm v10){
    return (v1|v2|v3|v4|v5|v6|v7|v8|v9|v10);
}

一亿次:

        for(Type y = 0; y < 10000; y++){
            for(Type x = 0; x < 10000; x++){
                out |= testfunc1(x,y,x,x,y,y,x,y,x,y);
            }
        }

对于类型intconst intconst int &,我注意到const intconst int &快。(注意:im使用返回值来确保函数不会被优化)。

为什么会这样?我一直认为添加&实际上会让它更快,但测试结果恰恰相反。我知道对于更大的数据类型,可能会有不同的结果,但我没有测试这些,因为我对结果很有把握。

我的测试:

const int: 7.95s
const int &: 10.2s

编辑:我认为这确实是因为我的架构;我用Sint64型进行了测试,结果是:

const Sint64: 17.5s
const Sint64 &: 16.2s

第2版:还是这样?用double型(哪种是64位?)测试,结果让我感到困惑:

const double: 11.28s
const double &: 12.34s

第3版:更新了循环代码,以匹配我最新的64位类型的测试。

通过在参数中放入&,可以为程序添加更多代码。如果没有&,序列为:

 push values
 call Function
 pop values <- usually an update to stack pointer

和在功能:

 return sp[arg1] | sp[arg2] | etc <- value read direct from stack.

正在添加"&"这样做吗:

 push address of value1
 push address of value2
 etc
 call Function
 pop values <- usually an update to stack pointer

和在功能:

 return_value = 0;
 address = sp[arg1]
 or return_value, [address]
 address = sp[arg2]
 or return_value, [address]
 etc
 return return_value

因此,正如您所看到的,&增加了很多。那么为什么要使用它呢?如果您有一个非常大的对象,那么传递指针比将对象复制到堆栈更为优化。

此结果严重依赖于系统。这表明在您的特定系统上,复制引用的值(很可能实现为指针)比复制整数的值成本更高。造成这种差异的最可能原因是,您的整数需要32位来表示,而指针/引用表示需要64位EDIT这还不算访问整数的成本:获取它们的值需要额外的间接寻址。由于您只传递两个项目,所以使用缓存在很大程度上隐藏了额外的成本,但成本是存在的。

不过,对于较大的类型,您是绝对正确的:传递对大型structvector<...>的引用仍然只需要64位(或系统中的任何大小),无论您的结构有多少项,或者vector<...>包含多少项。结构越大,通过价值传递的成本就越高,因此,通过将其作为参考可以实现节约。

传递地址而不是值会导致地址转义(在您喜欢的编译器教科书中查找转义分析或指向分析),从而使优化更加困难。

是的,像内联和链接时间优化这样的东西可以减轻这些问题。