虽然微优化很愚蠢,可能会导致实践中的许多错误。不管怎样,我见过很多人这样做:
void function( const double& x ) {}
改为:
void function( double x ) {}
因为它被认为是“更有效率的”。假设在程序中,
function
被无数次地调用,那么这种“优化”真的有意义吗?void function( const double& x ) {
double non_aliased_x = x;
// ... and use `non_aliased_x` from now on
...
}
但这将与首次通过引用传递的推荐理由相违背。
另一种解决别名问题的方法是使用某种类似于 C99 的 restrict
限定符。
void function( const double& restrict x ) {
但是,即使在这种情况下,按引用传递的缺点可能仍然会超过优点,正如其他答案所解释的那样。
double
复制到CPU堆栈中。得失相当。 - Steve Jessopdouble
:该(可能)8字节大小的值被写入堆栈并由函数原样读取。double &
或double *
:该值位于内存中的某个位置(可能“靠近”当前堆栈指针,例如如果它是局部变量,但也可能在远离的地方)。在堆栈上存储一个(可能)4或8字节大的指针地址(分别为32位或64位系统),函数需要取消引用地址才能读取该值。这还需要该值位于可寻址的内存中,而寄存器则不是。sizeof(T) > 32
或者可能更大时),请使用引用。当堆栈大小和热度起到非常重要的作用时,甚至在 sizeof(T) > sizeof(T*)
的情况下也是如此。
double
和指针都不是通过堆栈传递,而是通过寄存器传递,这种情况下差异要小得多... - twalberglong
的大小(以及其他类似的细节)的人也会写下调用约定。它们都是ABI的一部分,为了使两个二进制文件链接兼容,它们必须同时使用相同的ABI。如果在单个平台上使用多个调用约定(例如在Win32中),那么您可以使用调用约定装饰您的函数,这就像“C”链接一样成为函数签名的一部分。 - Steve Jessop
double
更小。问题的关键是:这种差异实际上是否会对我的(或你的)代码产生影响?要回答这个问题,需要提供一个具体的例子。 - Ed S.