考虑以下:
struct Point {double x; double y;};
double complexComputation(const& Point p1, const Point& p2)
{
// p1 and p2 used frequently in computations
}
Run Code Online (Sandbox Code Playgroud)
编译器是否将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
}
Run Code Online (Sandbox Code Playgroud)
由于Point是一个POD,通过在调用者的背后制作副本可以没有副作用,对吗?
如果是这种情况,那么我总是可以通过const引用传递POD对象,无论多小,都不必担心最佳传递语义.对?
编辑:我特别感兴趣的是GCC编译器.我想我可能要编写一些测试代码并查看ASM.
如果需要,您的编译器绝对可以将Point成员变量提升到寄存器 但是,这与将函数调用本身转换为pass by value的编译器不同.
您应该检查生成的程序集以查看正在执行的优化.
而FWIW,我使用的一般规则是在可能的情况下通过const引用按值和所有类/ UDT(POD或不是POD)传递所有主要类型,并让编译器找出最好的事情.我们不应该担心编译器正在做什么的细节,它比我们聪明得多.
有2个问题.
首先,编译器不会将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
Run Code Online (Sandbox Code Playgroud)
只有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
Run Code Online (Sandbox Code Playgroud)
请注意,此时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
}
Run Code Online (Sandbox Code Playgroud)
因为编译器可以识别经常使用的变量并将它们存储到保留寄存器(例如ARM架构中的r4~r13,以及许多sXX/dXX寄存器)以便更快地访问,所以可以轻松完成.
毕竟,如果你想知道编译器是否做了什么,你总是可以反汇编结果对象并进行比较.
归档时间: |
|
查看次数: |
4678 次 |
最近记录: |