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

13 c++ performance x86-64 pass-by-reference 32bit-64bit

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

假设32位机器:

1)32位int:我答案是"按值传递",因为"按引用传递"会产生额外的内存查找开销.

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

如果机器是64位怎么办?

问候,

J.P

Arm*_*yan 10

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


Cur*_*urd 9

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

  • 我会在64位机器上说*特别*. (7认同)

MSa*_*ers 7

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

  • +1对于担心优化整数传递的人来说,这是迄今为止最好的惩罚,他们必须输入那个批次. (12认同)

Nim*_*Nim 6

用一点常识,

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

  2. 如果要修改传入的值,请使用引用

  3. 否则,按值传递!

函数参数是否存在特定的性能瓶颈?否则,不要花太多时间担心哪个是最好的通过方式......

通过担心如何int传入来优化就像在大海中嬉戏......


Ton*_*roy 5

为了论证,让我们忽略优化器消除差异的微不足道的情况。假设您正在使用 Microsoft 的 Intel 64 位调用约定(与 Linux ABI 不同),那么您有 4 个 64 位寄存器用于传递这些值,然后才不得不求助于将它们推送到堆栈上。那显然更好。

对于 32 位应用程序,按值,它们会直接进入堆栈。按引用可以代替将指针放在寄存器中(同样,在求助于堆栈之前,允许使用一些这样的寄存器)。我们可以在 g++ -O3 -S 的一些输出中使用它,通过值调用 f1(99) 和通过常量引用调用 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!?!
Run Code Online (Sandbox Code Playgroud)

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

pst 建议的一个节点...

“效率” :( KISS。传递它如何传递所有其他该死的整数。- pst

...虽然,有时您将 KISS 应用于模板参数并使它们全部为 const T& 即使有些可能适合寄存器....