c++ 通过引用传递基元类型是否会产生相反的效果?[duplicate]

vlju58qv  于 2023-01-06  发布在  其他
关注(0)|答案(7)|浏览(97)
    • 此问题在此处已有答案**:

10年前关闭了。

    • 可能重复:**

Is it better to pass by value or by reference for basic datatypes?
Reasons to not pass simple types by reference?
我做了一些测试,我有两个场景,每个场景都有两个相同的函数--一个通过引用传递参数,另一个通过值传递参数。使用字符串的场景显示了巨大的性能提升(因为创建了一个字符串的副本,调用了一个构造函数),而使用long的测试在通过引用传递值时没有显示任何性能提升。事实上,有时性能更差。
这是原语类型所期望的吗?没有通过引用传递它们的点吗?
我希望在不通过引用使用的情况下创建基元类型的副本,因此希望性能有一点提升。

fwzugrvs

fwzugrvs1#

通过值传递基元类型可以获得最佳性能。这是因为:

  • 基元是可blitable的,因此拷贝的成本取决于大小
  • 图元很小,只有doublelong long比大多数环境中的参考大
    *按值传递可避免别名,从而使优化器能够真正发挥作用

这最后一点常常被忽视,但却能产生相当大的影响。

brgchamk

brgchamk2#

是的,这是预期的行为。当你通过引用传递参数时,你实际上是在传递变量的地址(就像指针一样)。通常地址是一个4或8字节的整数,所以除非你的基元类型比它大,否则你不会获得任何性能提升(即使它更大,你也可能不会)

w80xi6nr

w80xi6nr3#

现代的编译器非常聪明,所以如果函数不是“隐藏”的(也就是说,编译器在生成代码时看不到的部分),可能根本不会有什么不同。然而,如果编译器遵循你的指令,传递简单类型作为引用确实可能会有很大的不同。特别是如果代码中的值被多次更新。
我在我工作的地方看到一些代码,它是这样做的:

void SomeClass::FindLength(int &len)
{
     listEntry* list = theList;   // theList is a member variable. 
     len = 0;
     while (list)
     {
         len++;
         list = list->next;
     }
 }

通过更改代码执行以下操作:

void SomeClass::FindLength(int &len)
{
     listEntry* list = theList;   // theList is a member variable. 
     int tempLen = 0;
     while (list)
     {
         tempLen++;
         list = list->next;
     }
     len = tempLen;
 }

整个代码的运行速度提高了30%,并且从很多地方调用(我认为中间有一些if条件,所以我们不能只跟踪长度)。由于它是API函数的一部分,因此不可能更改函数签名。
使用引用时速度较慢的原因是编译器每次更新引用值时都会写入引用值,这是从内存到寄存器、从递增寄存器到存储寄存器的加载。使用tempLen解决方案时,编译器可以使用寄存器,速度会快得多。

b09cbbtk

b09cbbtk4#

在c++中引用只是使用指针的一种方便的方式。当你使用指针时你就增加了额外的间接寻址。复制原语类型和复制指针一样便宜。这就是为什么原语类型通过引用传递的速度会慢一些

pjngdqdw

pjngdqdw5#

因为您使用了c标记,所以我猜您是在谈论指针(而不是来自C++的显式引用)。
使用指针时,有两种内存访问方式:指针和被指向的值。所以没有特别的性能增益。而且,编译器可以对值做更多的优化:例如,不存在混叠问题。

4urapxun

4urapxun6#

这是基元类型所期望的吗?
我认为绝对是,它们没有构造函数,所以不需要调用它.
通过引用传递它们没有意义吗?
有:当你想有输出参数,那么,在C++中,通过引用传递被认为是比传递指针更好的实践。
我希望在不通过引用使用的情况下创建基元类型的副本,因此希望性能有一点提升。
好吧,因为通过引用传递通常是使用指针实现的,那么编译器必须发出代码,将一些东西推到堆栈上,要么是值,要么是指向值的指针--实际上是哪一个做的并不重要。

eiee3dmh

eiee3dmh7#

当你通过引用传递一个值的时候,函数必须解引用它来获得这个值,而且每次你修改这个值的时候,也必须解引用,因为你是在内存中写它。我猜编译器能够理解什么时候一些东西不会被存回它的引用位置,这样这个值就可以在寄存器中修改,并且在需要的时候存回,但是我不确定这有多强大。
所以有一个间接的步骤是不存在的,而传递参数的值,这可能会导致更差的性能,但它真的是模糊的,因为编译器优化到位.想想你传递一个指针的事实,每次你需要的值,你必须从堆栈中获取指针,然后获取指向的值(因此有两次访问),而使用普通参数时只有一次(获取值)。
在任何情况下,引用都是用于肯定与性能不同的目的,比如在本地修改传递的参数。

相关问题