成员函数与传递对全局函数的引用相同吗?

时间:2011-02-13 23:35:51

标签: c++ function methods

我能确定:

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吗?编译器可以更好地优化方法吗?

4 个答案:

答案 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不是虚拟的,编译器可能会以优化的方式做更多的事情。