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

C++ C++;64位int:按引用传递或按值传递,c++,performance,pass-by-reference,32bit-64bit,x86-64,C++,Performance,Pass By Reference,32bit 64bit,X86 64,这是一个关于64位整数的效率问题。假设我不需要修改“int”参数的值,我应该通过值或引用传递它吗 假设32位机器: 1) 32位int:我猜答案是“通过值传递”,因为“通过引用传递”将有额外的内存查找开销 2) 64位int:如果通过引用传递,则只传递堆栈上的32位地址,但需要额外的内存查找。那么,哪一个更好(参考或价值) 如果机器是64位的呢 问候, 即使在64位机器上,传递值也更好(只有少数例外),因为它可以作为寄存器值进行传递。传递值-绝对正确。如果系统是64位的,则意味着它复制64位字的

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

假设32位机器:

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

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

如果机器是64位的呢

问候,


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

传递值-绝对正确。如果系统是64位的,则意味着它复制64位字的速度非常快

为了论证起见,让我们忽略乐观主义者消除差异的琐碎例子。假设您使用的是Microsoft的Intel 64位调用约定(与Linux ABI不同),那么您就有4个64位寄存器来传递这些值,然后再将它们推送到堆栈上。这显然更好

对于32位应用程序,按值排序,它们将直接进入堆栈。By reference可以将指针放在寄存器中(同样,在使用堆栈之前允许使用一些这样的寄存器)。我们可以在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!?!
然后,调用的函数必须在首次使用之前进行检索(如果有的话)。被调用函数可以自由缓存寄存器中读取的值,因此只需要一次。使用堆栈方法,可以随意重新读取该值,因此不需要为该值保留寄存器。使用指针方法,如果需要暂时释放寄存器以进行其他工作,则指针或64位值可能需要保存在更可预测的位置(例如,推送寄存器或另一个不太有用的寄存器),但稍后需要64位int参数。总而言之,很难猜测哪一个更快-可能是CPU/寄存器使用率/优化程序/等等,不值得尝试

pst建议的节点

“效率”:(接吻。以你每隔一个该死的整数的方式传递它。-pst


…尽管如此,有时您会将KISS应用于模板参数并使其全部为常量,即使有些参数可能适合于寄存器….

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

使用一些常识

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

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

  • 否则,按价值传递

  • 函数的参数是否存在特定的性能瓶颈?否则,不要花太多时间担心哪种方法是传递函数的最佳方法


    通过担心
    int
    是如何传递进来的来优化就像是在海里钓鱼……

    “效率”:(吻。以传递其他该死的整数的方式传递它。编译器可能会对它进行优化。@pst:+1作为有趣的注释。伙计,我笑得很厉害。任何像样的32位代码生成器都会在两个CPU寄存器中传递值,或者在堆栈帧上只传递普通的8个字节。例如,对于结构也是如此。你不应该开始考虑传递一个指针,直到它超过16字节。@Hans:谢谢你对我的问题的清晰和切中要害的评论。我要说的是,特别是在64位机器上。因此,在32位或64位机器上,“按值”传递64位int比“按引用”传递64位int更有效(在64位机器上更是如此),对吗?我很想知道例外情况(这并不超出讨论的范围:)@JP19:我不确定是否存在这样的异常。可能以下情况就是这样的异常:调用者有太多的局部变量,以至于不是所有的变量都可以保存在寄存器中,并且参数的地址最近正在使用,所以它仍然存在于寄存器中。但是这些假设太深奥了,可能不值得考虑g、 ..+1对于那些担心优化整数传递的人来说,这是迄今为止最好的惩罚,因为他们必须输入这些数据。也许64位数据的差异可以忽略不计。但是,我认为这个问题的精神是值得的。如果我有一个12字节的结构,16字节呢?Hans Passant的评论,尽管可能不是技术性的经过严格验证或测试,至少给出了正确方向的指示。当然,知道64位无需担心这一点很有用:)(尽管我们的代码将调用此类函数1亿次,通常运行数小时。在这种情况下,遵循“最佳”实践总是很好的)。