我能确定:
class foo {
public:
int x;
void bar(int k) {
x = k;
}
};
foo o;
o.bar(5);
将与:
相同class foo {
public:
int x;
};
void foobar(foo& f, int k) {
f.x = k;
}
foo o;
foobar(o, 5);
我知道两者都会将“x”设置为“k”,但我可以确定它们都以相同的速度运行/生成相同的asm吗?编译器可以更好地优化方法吗?
答案 0 :(得分:3)
生成汇编程序并比较(GCC的-S
标志)。
答案 1 :(得分:2)
在少数情况下,可以在生成的汇编代码中产生差异,但(至少通常)并不多。
例如,Microsoft的编译器将(通常)使用他们称为成员函数的thiscall
调用约定,在这种情况下,this
指针在寄存器ECX中传递。全局函数默认为cdecl
调用约定,其中参数都在堆栈上传递。但是,也可以告诉编译器使用fastcall
调用约定,其中前两个参数分别在ECX和EDX中传递(只要你传递模仿 - this
为第一个参数,它最终与thiscall
)相同。
多年前(例如,286,386时间帧),在寄存器中而不是在堆栈上传递参数节省了相当多的时间。现在大多数CPU至少有几兆字节的板载缓存,大部分差异已经消失。
答案 2 :(得分:1)
我知道两者都会将“x”设置为“k”,但我可以确定它们都以相同的速度运行/生成相同的asm吗?
实际上,你可以确定无关紧要。如果您认为这很重要,那么可以对差异进行分析和比较,或者查看编译器的asm输出。
编译器可以更好地优化方法吗?
一般情况下不能。特别是对于简短的,内联的,非虚函数,如你的例子中所示(你需要将foobar标记为内联以完全等同于第一段代码),在任何一种情况下函数调用都可能简单地消失。
答案 3 :(得分:-2)
第一个例子在类foo的虚函数表中有foo :: bar。第二个没有。这使它更节省空间。由于foobar不是虚拟的,编译器可能会以优化的方式做更多的事情。