在C ++中,通过引用传递原始类型而不是按值返回是否有效率优势?
答案 0 :(得分:8)
[...]通过引用传递原始类型而不是按值返回是否有效率优势?
不太可能。首先,除非您的分析器中有数据表明您有其他原因,否则在设计程序时不必担心性能问题。选择最简单的设计,以及最能传达您意图的设计。
此外,原始类型的复制通常很便宜,因此这不太可能成为您应用程序的瓶颈。因为它是最简单的选项,也是使函数界面最清晰的选项,你应该按值传递。
只要查看签名,很明显有一个功能如:
void foo(int);
不会存储对参数的引用(因此,不会遇到诸如悬空引用或指针之类的问题),不会以调用者可见的方式更改参数,依此类推等等
上述所有内容均不能从以下函数签名中推断出来:
void f(int&); // May modify the argument! Will it? Who knows...
甚至:
void f(int const&); // May store a reference! Will it? Who knows...
此外,通过允许编译器执行潜在别名会阻止的优化,传递值甚至可以提高性能。
当然,所有这一切都假设您实际上不需要修改函数内部的参数,以便在函数返回后调用者可以看到对该参数的副作用 - 或者存储一个参考那个论点。
如果是这种情况,那么您当然应该通过引用传递并使用适当的const
资格。
有关更广泛的讨论,请参阅this Q&A on StackOverflow。
答案 1 :(得分:2)
一般情况下,没有任何性能优势,可能会有性能成本。请考虑以下代码:
void foo(const int& a, const int& b, int& res) {
res = a + b;
res *= a;
}
int a = 1, b = 2;
foo(a, b, a);
当编译器遇到类似add()的函数时,必须假设a和res可能在示例调用中可能是别名,因此如果没有全局优化,它将必须生成加载a,加载b,然后存储结果的代码+ b到res,然后再次加载并执行乘法,然后将结果存储回res。
如果您改为编写了这样的函数:
int foo(int a, int b) {
int res = a + b;
res *= a;
return res;
}
int a = 1, b = 2;
int c = foo(a, b);
然后编译器可以将a和b加载到寄存器中(或者甚至直接在寄存器中传递它们),在寄存器中添加和相乘然后返回结果(在许多调用约定中可以直接在寄存器中返回它生成于)。
在大多数情况下,您实际上需要foo的pass / return by value版本中的语义,并且实际上不需要支持pass / return by reference版本中可能存在的别名语义。您最终可以通过参考版本的传递/返回来支付真正的性能损失。
Chandler Carruth在C ++ Now上提出了一个很好的talk。
答案 2 :(得分:1)
在这种情况下可能存在一些模糊的体系结构,但我不知道返回的内置类型比通过引用传递out参数更低的性能。如果需要,您可以随时检查相关装配以进行比较。