Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 创建通过引用传递的新变量与通过值传递的新变量相比,是否有任何性能提升?_Performance_Variables_Reference - Fatal编程技术网

Performance 创建通过引用传递的新变量与通过值传递的新变量相比,是否有任何性能提升?

Performance 创建通过引用传递的新变量与通过值传递的新变量相比,是否有任何性能提升?,performance,variables,reference,Performance,Variables,Reference,我对具体的价值观不感兴趣,只对理论上的答案感兴趣 例如,当我们需要时,在循环中 在和上使用相同的值 结束后,如果 将改为通过引用传递 有价值吗 那么物体呢?假设 我们的对象包含一些值 对于 对象而不是实例化新的 对象,我们可以通过引用传递它吗 为了获得更高的性能?或者应该 我们要克隆它吗 我希望我已经说清楚了,提前谢谢。当然。通过引用传递实际上总是一个巨大的成功,特别是对于必须运行非平凡构造函数和析构函数的类类型。只有在传递小于指针的数据(例如单个字符)的情况下,通过值才能获胜。即使如此,这也是

我对具体的价值观不感兴趣,只对理论上的答案感兴趣

  • 例如,当我们需要时,在循环中 在和上使用相同的值 结束后,如果 将改为通过引用传递 有价值吗

  • 那么物体呢?假设 我们的对象包含一些值 对于 对象而不是实例化新的 对象,我们可以通过引用传递它吗 为了获得更高的性能?或者应该 我们要克隆它吗


  • 我希望我已经说清楚了,提前谢谢。

    当然。通过引用传递实际上总是一个巨大的成功,特别是对于必须运行非平凡构造函数和析构函数的类类型。只有在传递小于指针的数据(例如单个字符)的情况下,通过值才能获胜。即使如此,这也是一个非常特定于硬件的参数。

    如果您只关心性能,那么作为一般规则,“按引用传递”比“按值传递”性能更好。

    按值传递复制值-如果它是一个小的原语-例如,int,这无关紧要-您可以将int复制到堆栈以进行调用,或者复制其地址(大小大致相同,因此没有实际增益)

    对于一个大型的非平凡对象,传递值的成本要高得多——您需要构建该对象的新副本


    不清楚您对循环的定义是什么-PBV/PBR主要只在函数调用期间起作用。

    现代CPU的一般规则是“数学快,内存慢”

    如果你谈论C++,通过值传递整数、浮点,甚至小对象可能会更快。由于别名问题,通过引用传递可以防止各种编译器优化

    对于较大的对象,通过引用传递将更快。(绝对不要克隆它们,因为内存很慢。)

    不过,这个问题的真正答案是以一种自然、直接的方式编写代码,在分析器告诉您之前,不要担心这类问题

    [更新,详细说明别名问题]

    例如,考虑以下两个函数:

    void
    foo1(int a, int b, int &c, int &d)
    {
        c = a + b;
        d = a - b;
    }
    
    void
    foo2(const int &a, const int &b, int &c, int &d)
    {
        c = a + b;
        d = a - b;
    }
    
    启用优化后,我的编译器(gcc 4.5.2,x86_64)为foo1生成以下代码:

    leal    (%rsi,%rdi), %eax
    subl    %esi, %edi
    movl    %eax, (%rdx)
    movl    %edi, (%rcx)
    ret
    
    …对于foo2:

    movl    (%rsi), %eax
    addl    (%rdi), %eax
    movl    %eax, (%rdx)
    movl    (%rdi), %eax
    subl    (%rsi), %eax
    movl    %eax, (%rcx)
    ret
    
    您的编译器将执行类似的操作。问题是,在foo2中,“c”或“d”可能与“a”或“b”引用相同的内存位置,因此编译器必须插入额外的加载/存储来担心这种情况


    这是一个微不足道的例子,但更复杂的例子显示了类似的行为。对于简单类型甚至小结构,传递值通常会导致更快的代码。

    这取决于语言和实现。通常,通过引用传递更快,因为您只需要传递一个地址(指针)。对于小于指针的数据类型,可能会节省少量内存和/或传递值的时间。然而,在大多数语言中,即使复制一个小对象也需要调用某种类型的复制构造函数,这将扼杀任何可能的节省。另一方面,通过引用传递会创建对象或变量别名,这在某些语言中可能是个问题。此外,在某些语言中,不能通过引用传递编译时常量;编译器将调用
    func(1)
    转换为
    int\u 1=1;func(_1)


    我还应该提到,在某些语言(如Java)中,不可能通过值传递对象或通过引用传递基元类型。当然,对于这些语言,您的问题是没有意义的。

    在某种程度上,这取决于语言。(或者至少是一个好答案的细节)你指的是PHP吗?@middaparka,我指的是PHP,但我很高兴得到与其他语言相关的答案。PHP不同于其他语言。当通过值传递时,许多语言复制值,然后传递此副本。PHP会创建一个新的“引用”值,并仅在值被更改时复制该值。例如,如果创建1MB字符串并将其设置为3个变量的值(
    $str='…';$str2=$str;$str3=$str;
    ),则只会得到一个大小为1MB的值和指向相同值的3个变量。当您修改一个值(例如,<代码> $STR3)时,值被复制并编辑,并被分配给<代码> $STR3,因此现在您有1个变量指向新的1MB值,2个变量,到旧的值。在C++中,通常通过const引用,除非函数只与引用相关的是复制。在这种情况下,按值传递,使编译器有更好的机会优化副本。@Ben:那根本不是真的。引用的问题是它们可以使用别名,这使得编译器很难将子表达式提升到寄存器中,将它们提升到循环中,等等。这两个函数的行为不同。如果
    d
    是根据函数输入时
    a
    b
    的值来计算的,则需要复制它们。。。在这种情况下,我的规则是按值传递,让编译器执行复制。还要注意的是,程序集列表并没有提供太多关于性能的信息。只有在缓存未命中时,内存才会变慢。关于循环,我的意思是在循环中运行一个与这些值一起工作的函数(PBV/PBR)。@Tom在这种情况下,如果对象非常重要,您肯定希望通过引用传递,否则,每次调用都会导致您构建对象的新副本。最基本的是,如果我为您提供了一个对象,那么您在函数中所做的任何更改都是对象副本的本地更改-如果您想编写一个查找zip+4代码并在对象上进行设置的函数,则必须使用PBR。出于同样的原因,您必须更加担心常量的正确性(您不希望某些子函数