C ++编译器是否通过const引用POD参数优化传递?

时间:2010-01-11 18:34:13

标签: c++ optimization

请考虑以下事项:

struct Point {double x; double y;};

double complexComputation(const& Point p1, const Point& p2)
{
    // p1 and p2 used frequently in computations
}

编译器是否会将pass-by-reference优化为pass-by-copy以防止频繁解除引用?换句话说,将complexComputation转换为:

double complexComputation(const& Point p1, const Point& p2)
{
    double x1 = p1.x; double x2 = p2.x;
    double y1 = p1.y; double y2 = p2.y;
    // x1, x2, y1, y2 stored in registers and used frequently in computations
}

由于Point是一个POD,通过在调用者后面复制一个副本没有副作用,对吗?

如果是这种情况,那么我总是可以通过const引用传递POD对象,无论多小,都不必担心最佳传递语义。正确?

编辑: 我特别感兴趣的是GCC编译器。我想我可能要编写一些测试代码并查看ASM。

3 个答案:

答案 0 :(得分:7)

如果需要,您的编译器可以绝对将Point成员变量提升到寄存器中。但是,这与编译器将函数调用本身转换为按值传递不同。

您应该检查生成的程序集以查看正在进行的优化。

而FWIW,我使用的一般规则是在可能的情况下通过const引用按值和所有类/ UDT(POD或不是POD)传递所有原始类型,并让编译器整理出最好的事情。我们不应该担心编译器正在做什么的细节,它比我们聪明得多。

答案 1 :(得分:5)

有两个问题。

首先,编译器将将pass-by-ref转换为pass-by-value,尤其是complexComputation不是static时(即可以由外部使用)对象)。

原因是API兼容性。对于CPU,没有“引用”这样的东西。编译器将引用转换为指针。参数在堆栈或寄存器中传递,因此调用complexComputation的代码可能会被调用为(假设double长度为4):

str x1, [r7, #0x20]
str y1, [r7, #0x24]
str x2, [r7, #0x50]
str y2, [r7, #0x54]
push r7, #0x20     ; push address of p1 onto the stack
push r7, #0x50     ; push address of p2 onto the stack
call complexComputation

只有8个字节被压​​入堆栈。

另一方面,通过副本将整个结构推入堆栈,因此汇编代码看起来像

push x1    ; push a copy of p1.x onto the stack
push y1    ; push a copy of p1.y onto the stack
push x2    ; push a copy of p2.x onto the stack
push y2    ; push a copy of p2.y onto the stack
call complexComputation

请注意,此时16个字节被压​​入堆栈,内容是数字,而不是指针。如果complexComputation更改其参数传递语义,输入将​​变为垃圾,您的程序可能会崩溃。


另一方面,优化

double complexComputation(const Point& p1, const Point& p2) {
    double x1 = p1.x; double x2 = p2.x;
    double y1 = p1.y; double y2 = p2.y;
    // x1, x2, y1, y2 stored in registers and used frequently in computations
}

可以轻松完成,因为编译器可以识别经常使用的变量 将它们存储到保留寄存器(例如ARM体系结构中的r4~r13,以及许多sXX / dXX寄存器)以便更快地访问。


毕竟,如果你想知道编译器是否做了什么,你总是可以反汇编结果对象并进行比较。

答案 2 :(得分:4)

我不能代表每个编译器,但一般答案是否。它不会进行优化。

请参阅GOTW#81,了解C ++中对const的转换如何不会像某些人想的那样影响优化。