C ++ 64位int:按引用传递或按值传递

时间:2010-11-10 10:50:21

标签: c++ performance pass-by-reference 32bit-64bit x86-64

这是一个关于64位整数的效率问题。假设我不需要修改“int”参数的值,我应该通过值或引用传递它。

假设32位机器:

1)32位int:我答案是“按值传递”,因为“按引用传递”将有额外的内存查找开销。

2)64位int:如果我通过引用传递,我只在栈上传递32位地址,但需要额外的内存查找。那么哪一个更好(参考或价值)?

如果机器是64位怎么办?

的问候,

JP

5 个答案:

答案 0 :(得分:9)

通过价值 - 肯定。如果系统是64位,则意味着它可以非常快速地复制64位字。

答案 1 :(得分:8)

即使在64位机器上,传递值也更好(除了极少数例外),因为它可以作为寄存器值传递。

答案 2 :(得分:7)

将它们作为boost::call_traits<int64_t>::param_type传递。此模板捕获在支持的平台上传递任何类型的最佳实践。因此,它在32位和64位平台上会有所不同,但您可以在任何地方使用相同的代码。它甚至适用于您还不知道精确类型的其他模板。

答案 3 :(得分:4)

出于论证的缘故,让我们忽略优化器删除差异的微不足道的情况。我们还说你正在使用微软的英特尔64位调用约定(它与Linux ABI不同),那么你必须有4个64位寄存器来传递这些值,然后才能在堆栈上推送它们。这显然更好。

对于32位应用程序,按值并且它们会直接进入堆栈。引用可以改为将指针放在寄存器中(同样,在求助于堆栈之前允许一些这样的寄存器使用)。我们可以在g ++ -O3 -S的某些输出中,通过值调用f1(99)和通过const引用调用f2(101):

void f1(int64_t);
void f2(const int64_t&);

int main()
{
    f1(99);
    f2(101);
}

...

    pushl   0
    pushl   $99
    call    _Z2f1x    // by value - pushed two halves to stack

    leal    -8(%ebp), %eax
    movl    %eax, (%esp)
    movl    $101, -8(%ebp)
    movl    $0, -4(%ebp)
    call    _Z2f2RKx   // by const& - ugly isn't it!?!

然后必须在第一次使用之前检索被调用的函数(如果有的话)。被调用函数可以自由地缓存寄存器中读取的值,因此只需要一次。使用堆栈方法,可以随意重读该值,因此不需要为该值保留寄存器。使用指针方法,指针或64位值可能需要保存在更可预测的地方(例如,推送或另一个不太有用的寄存器),如果该寄存器需要暂时释放以用于其他一些工作,但是64位稍后需要再次使用int参数。总而言之,很难猜出哪个更快 - 可能是CPU /寄存器使用/优化/等依赖,并且不值得尝试。

pst建议的节点......

“效率”:( KISS。传递它如何通过其他所有血腥整数。 - pst

...但是,有时你会将KISS应用于模板参数并使它们全部成为const T&amp;即使有些可能适合寄存器......

答案 4 :(得分:3)

使用一点常识,

  1. 如果对象需要一个复杂的复制构造函数,它可能值得通过引用传递(说 - 很多boost的对象被设计为按值传递而不是参考,因为内部实现非常简单)有一个奇怪的我没有真正解决过,std::string,我总是通过参考传递这个......

  2. 如果您打算修改传入的值,请使用引用

  3. 另外,PASS-BY-VALUE!

  4. 您是否存在功能参数的特定性能瓶颈?另外,不要花太多时间担心哪种方式最好通过......

    通过担心如何传递int进行优化就像在海中嬉戏一样......