0

当将参数传递给将在短时间内被调用数百万次的函数和方法时,传递所述参数的开销开始显现。

void foo(const SomeType& st) { ... }

对于 std::string、std::vector 等类型,规则是通过引用传递,这样就不会出现无意义的复制。然而,在处理诸如双打、整数等 POD 时,情况就完全不同了。

关于性能,如果函数/方法不需要改变参数,那么在决定是否应该通过引用、常量引用或复制传递时,常见的“需要注意的事项”是什么?

void foo1(SomeType& st)
{
   ...
}

void foo2(const SomeType& st)
{
   ...
}

void foo3(SomeType st)
{
   ...
}

void foo4(SomeType* st)
{
   ...
}
  • 是否应该始终通过副本传递 int/unsigned int?
  • 是否应该仅在 64 位或更高的目标上通过副本传递双精度?
  • 如果函数可以内联 - 参数的传递方式是否重要?
  • 通过 ref/const ref 传入时,别名如何影响问题?
  • 在什么情况下,参数的显式副本对堆栈有益?

注意:这不是关于 const 正确性的问题。还寻找与 32/64 位平台上的 gcc 和 msvc 相关的答案。

一些可能相关的问答:

"const T &arg" 与 "T arg"

https://stackoverflow.com/a/2139254/754951

在 C++ 中通过引用/值传递

为什么要通过 const 引用而不是按值传递?

4

1 回答 1

6

最好的答案是让您阅读平台中的调用约定,但一般来说,对于小类型(那些适合寄存器甚至有时稍大的类型),按值传递通常会更快。当您通过指针或引用传递时,指针是按值传递的,这与复制原始对象的成本相同,而且还需要取消引用。

当对象变大时,复制指针加上取消引用的成本通常会小于复制大对象的成本,因此您应该使用引用。如果您不打算修改对象,请通过const&.

是否应该始终通过副本传递 int/unsigned int?是否应该仅在 64 位或更高的目标上通过副本传递双精度?

即使在 32 位架构中,您也应该按值传递整数和双精度数。同样,查看您的体系结构的调用约定(通常与编译器一起记录)。

如果函数可以内联 - 参数的传递方式是否重要?

如果函数是内联的,编译器可以对其进行优化,例如,通过将引用的使用替换原对象的使用来消除引用的成本。

通过 ref/const ref 传入时,别名如何影响问题?

如果您不打算修改参数(正如您在问题中声称的那样),别名将无关紧要。如果您传递可以以算法不期望的方式修改的指针/引用,您将遇到别名问题。

在什么情况下,参数的显式副本对堆栈有益?

忽略堆栈部分:当对象很小时。请注意,使用的调用约定甚至可能不使用堆栈(它可能会在寄存器中传递值)。我建议你阅读这篇关于不同调用约定的文章

于 2012-05-26T22:27:49.633 回答