【问题标题】:Does const call by reference improve performance when applied to primitive types?const 引用调用是否会在应用于原始类型时提高性能?
【发布时间】:2015-05-22 09:29:46
【问题描述】:

关于对象(尤其是字符串),按引用调用比按值调用更快,因为函数调用不需要创建原始对象的副本。使用 const 还可以确保引用不被滥用。

我的问题是,如果使用基本类型(如 bool、int 或 double),const 引用调用是否也更快。

void doSomething(const string & strInput, unsigned int iMode);
void doSomething(const string & strInput, const unsigned int & iMode);

我的怀疑是,只要原始类型的字节大小超过地址值的大小,就使用引用调用是有利的。即使差异很小,我也想利用它,因为我经常调用其​​中一些函数。

附加问题:内联对我的问题的答案有影响吗?

【问题讨论】:

  • 大多数时候应该没有效果。但是针对特定案例进行分析会很好。我通过值传递原始类型,通过 const 引用传递对象。内联不应该改变任何东西。
  • 重要的是要理解它们不是一回事(参考stackoverflow.com/questions/4705593/int-vs-const-int 例如)。选择符合您需求的那个 - 如果按值传递就足够了,那么就这样做 - 如果需要通过引用传递,那么就这样做。

标签: c++ performance call-by-value


【解决方案1】:

我的怀疑是,只要原始类型的字节大小超过地址值的大小,就使用引用调用是有利的。即使差异很小,我也想利用它,因为我经常调用其​​中一些函数。

基于预感的性能调整在 C++ 中大约 0% 的时间起作用(这是我对统计数据的直觉,它通常会起作用......)

如果sizeof(T) > sizeof(ptr)const T& 将小于T 是正确的,因此通常为 32 位或 64 位,具体取决于系统..

现在问问自己:

1) 有多少内置类型大于 64 位?

2) 复制 32 位不值得让代码不那么清晰吗?如果您的函数因为没有向其复制 32 位值而变得明显更快,也许它并没有起到太大作用?

3) 你真的那么聪明吗? (剧透警报:不。)请参阅这个很好的答案,因为它几乎总是一个坏主意: https://stackoverflow.com/a/4705871/1098041

最终只是按值传递。如果在(彻底)分析之后您发现某个函数是一个瓶颈,并且您尝试的所有其他优化都还不够(并且您应该在此之前尝试其中的大部分),请通过 const-reference 传递。

然后看看它没有改变任何东西。翻身哭泣。

【讨论】:

    【解决方案2】:

    除了其他答案之外,我想指出的是,当您在函数中传递引用并大量使用(也称为取消引用)时,它可能比制作副本要慢。

    这是因为函数的局部变量(通常)被一起加载到缓存中,但是当其中一个是指针/引用并且函数使用它时,可能会导致缓存未命中。这意味着它需要去(较慢的)主内存来获取指向的变量,这可能比制作与函数一起加载到缓存中的副本要慢。

    因此,即使是“小对象”,仅按值传递也可能更快。

    (我在一本非常好的书中读到:Computer Systems: a programmers perspective

    关于整个缓存命中/未命中主题的一些更有趣的讨论:How does one write code that best utilizes the CPU cache to improve performance?

    【讨论】:

      【解决方案3】:

      在 64 位架构上,没有比指针/引用更大的原始类型(至少在 C++11 中没有)。您应该对此进行测试,但直观地说,const T& 的数据量应该与int64_t 的数据量相同,而sizeof(T) < sizeof(int64_t) 的任何原语的数据量更少。因此,只要您可以测量任何差异,按值传递原语应该会更快如果您的编译器正在做显而易见的事情---这就是为什么我强调如果您需要确定性,您应该编写一个测试用例。

      另一个考虑因素是原始函数参数可以在 CPU 寄存器中结束,这使得访问它们的速度与内存访问一样快。当T 是一个原语时,您可能会发现为您的const T& 参数生成的指令比为您的T 参数生成的指令更多。您可以通过检查编译器的汇编器输出来测试它。

      【讨论】:

        【解决方案4】:

        我被教导:

        • 按值传递,当参数变量是基本内置类型之一时,例如 boolintfloat。这些类型的对象非常小,以至于通过引用传递并不会提高效率。另外,如果您想复制变量。

        • 在您想要有效地传递不需要更改的值时传递一个常量引用。

        • 仅在您想要更改参数变量的值时传递引用。但要尽量避免更改参数变量。

        【讨论】:

          【解决方案5】:

          const 是在编译时评估的关键字。它对运行时性能没有任何影响。您可以在此处阅读更多相关信息:https://isocpp.org/wiki/faq/const-correctness

          【讨论】:

          • const 不会对性能产生负面影响,因为它纯粹是编译时的事情。但是,它可能仍然对智能编译器产生积极影响。
          猜你喜欢
          • 1970-01-01
          • 2021-08-29
          • 1970-01-01
          • 2017-07-18
          • 1970-01-01
          • 2014-01-23
          • 2010-10-14
          • 2011-09-24
          • 2020-01-15
          相关资源
          最近更新 更多