这可能是一个愚蠢的问题,但我注意到在许多API中,许多采用不打算修改的整数参数的方法签名如下所示:
void method(int x);
而不是:
void method(const int &x);
对我来说,看起来这两个功能完全相同。 (编辑:显然不是在某些情况下,请参阅R Samuel Klatchko的回答)在前者中,价值被复制,因而无法改变原作。在后者中,传递了一个常量引用,因此原始内容无法更改。
我想知道的是为什么一个在另一个之上 - 是因为前者的表现基本相同甚至更好?例如传递16位值或32位值而不是32位或64位地址?这是我能想到的唯一合乎逻辑的原因,我只是想知道这是否正确,如果没有,为什么以及何时应该更喜欢int x
而不是const int &x
,反之亦然。
答案 0 :(得分:53)
这不仅仅是传递指针的成本(基本上是引用的成本),而且还是在被调用方法的主体中取消引用以检索基础值。
这就是为什么传递int
的值几乎可以保证更快(同样,编译器可以优化并简单地通过处理器寄存器传递int
,从而无需将其推入堆栈)。
答案 1 :(得分:36)
对我来说,看起来两者的功能完全相同。
这取决于参考的确切内容。这是一个公认的组成示例,它将根据您是传递引用还是值来更改:
static int global_value = 0;
int doit(int x)
{
++global_value;
return x + 1;
}
int main()
{
return doit(global_value);
}
此代码的行为会有所不同,具体取决于您是int doit(int)
还是int doit(const int &)
答案 2 :(得分:2)
整数通常是处理器本机字的大小,可以轻松传递到寄存器中。从这个角度来看,传递值或传递常量引用没有区别。
如有疑问,请打印函数的汇编语言列表,以了解编译器如何传递参数。打印输出值,并通过常量参考传递。
此外,当传递值时,该函数可以修改副本。当通过常量引用传递时,该函数不能修改变量(它标记为const)。
答案 3 :(得分:1)
根据底层指令集,整数参数可以作为寄存器或堆栈传递。寄存器肯定比内存访问更快,在const refs的情况下总是需要(考虑早期无缓存架构)
您不能将int文字作为const int&
显式类型转换允许你转换const int& into *(const int *)打开更改传递引用值的可能性
答案 4 :(得分:0)
通过引用传递可能会有一个非常非常小的去优化,因为至少需要一个去引用才能获得实际值(除非调用内联,编译器不能简单地传递值由于调用站点和函数可能是单独编译的,并且它是有效且定义良好的,以抛弃const
传递的参数本身并非const
本身 - 请参阅{{ 3}})。但请注意,“去优化”可能很小,难以衡量。
大多数人似乎不喜欢内置插件的const-by-const因为这个(非常多)。但是,我认为在某些情况下,如果您希望编译器帮助您确保在函数中不会意外更改该值,则可能更为可取。这不是一件大事,但有时它可能会有所帮助。