通过引用传递原始类型而不是按值返回的任何效率优势?

时间:2013-06-16 13:34:46

标签: c++ performance

在C ++中,通过引用传递原始类型而不是按值返回是否有效率优势?

3 个答案:

答案 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参数更低的性能。如果需要,您可以随时检查相关装配以进行比较。