如果您启用了链接时间优化并且优化级别足够高,GCC 绝对可以跨编译单元进行优化,请参见此处:https://gcc.gnu.org/wiki/LinkTimeOptimization https://gcc.gnu.org/wiki/LinkTimeOptimization除了编译时间之外,确实没有理由不执行这两件事。
此外,您始终可以通过使用适当的属性标记函数来帮助编译器。您可能想使用属性 const 来标记该函数,如下所示:
struct foo {
member_type m;
return_type f() const __attribute__((const)); // returns by value
};
请查看此处的 GCC 文档,了解哪个属性合适:https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
从更一般的意义上来说,编译器很容易检测到这一点。它实际上执行不太明显的转换。然而,链接时间优化之所以重要的原因是,一旦 GCC 生成了实际的机器代码,它就不会真正知道此时做什么是安全的。例如,您的函数可以修改数据(在您的类之外)或访问易失性变量。
EDIT:
GCC 绝对可以做到这一点优化。使用此代码和标志 -O3 -fno-inline:
C++代码:
#include <iostream>
int function(int c){
for(int i = 0; i != c; ++i){
c += i;
}
return c;
}
int main(){
char c;
::std::cin >> c;
return function(c) + function(c) + function(c) + function(c) + function(c);
}
装配输出:
4006a0: 48 83 ec 18 sub rsp,0x18
4006a4: bf 80 0c 60 00 mov edi,0x600c80
4006a9: 48 8d 74 24 0f lea rsi,[rsp+0xf]
4006ae: e8 ad ff ff ff call 400660 <_ZStrsIcSt11char_traitsIcEERSt13basic_istreamIT_T0_ES6_RS3_@plt>
4006b3: 0f b6 7c 24 0f movzx edi,BYTE PTR [rsp+0xf]
4006b8: e8 13 01 00 00 call 4007d0 <_Z8functioni>
4006bd: 48 83 c4 18 add rsp,0x18
4006c1: 8d 04 80 lea eax,[rax+rax*4]
4006c4: c3 ret
4006c5: 66 66 2e 0f 1f 84 00 data32 nop WORD PTR cs:[rax+rax*1+0x0]
4006cc: 00 00 00 00
但是,当函数位于单独的编译单元中并且未指定 -flto 选项时,它确实无法执行此操作。只是为了澄清一下,这一行调用了该函数:
call 4007d0 <_Z8functioni>
此行将结果乘以 5(将五个副本加在一起):
lea eax,[rax+rax*4]