【问题标题】:Member functions same as passing reference to global function?成员函数与传递对全局函数的引用相同吗?
【发布时间】:2011-06-26 15:17:59
【问题描述】:

我可以确定:

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 吗?编译器能否对方法进行更大的优化?

【问题讨论】:

  • @KennyCason:这可能是真的,但我不希望他接受答案纯粹是为了像你鼓励的那样增加一些无意义的统计数据。
  • 很公平,但是他提出的 75% 的问题没有得到合适的可接受答案的几率是多少? :P
  • @Kenny:老实说我不在乎,只要这个问题对我来说很有趣,我会花时间阅读它及其答案,并且(如果我有心情)也许甚至可以提出我的一些答案。我不明白人们正在关注那个“接受率”参数......
  • @Matthieu 我同意,如果这是一个很酷的问题(而且我知道答案),我仍然会回答。我确实对这个问题很感兴趣。我想这就是提出问题但不提供任何反馈的整个过程,这有点粗鲁,有点违背 SO,IMO。

标签: c++ function methods


【解决方案1】:

生成汇编程序并进行比较(GCC 的-S 标志)。

【讨论】:

  • 我想知道对于更大的方法是否会有所不同,但到目前为止我确信。
【解决方案2】:

在少数情况下,它可以对生成的汇编代码产生影响,但(至少通常)影响不大。

例如,Microsoft 的编译器将(通常)使用他们所谓的 thiscall 成员函数调用约定,在这种情况下,this 指针在寄存器 ECX 中传递。全局函数默认为cdecl 调用约定,其中参数全部在堆栈上传递。但是,也可以告诉编译器使用 fastcall 调用约定,其中前两个参数分别在 ECX 和 EDX 中传递(只要您将模仿 -this 作为第一个参数传递,它最终与thiscall 相同。

几年前(例如,286、386 时间帧),在寄存器中而不是在堆栈中传递参数节省了相当多的时间。现在大多数 CPU 至少有几兆字节的板载缓存,大部分差异已经消失。

【讨论】:

  • 我应该告诉编译器对 foobar 使用“thiscall”约定吗?
  • @Pepe:至少 AFAIK,虽然您可以指定 __cdecl__fastcall,但没有匹配的 __thiscall。默认只能获取thiscall
  • @Pepe:不,你不应该!除非你完全确定这是必要的。看起来您正在尝试在这里进行一些过早的非优化。
  • @7vies 实际上,我已经在指定调用约定,因为我正在使用函数指针
  • @Pepe:通常你不必指定调用约定来使用函数指针,所以我不确定我是否明白你的意思。
【解决方案3】:

我知道两者都会将“x”设置为“k”,但我可以确定它们都以相同的速度执行/生成相同的 asm?

实际上,您可以确定这无关紧要。如果您认为这很重要,请分析并比较差异,或查看编译器的 asm 输出。

编译器能否更好地优化方法?

一般情况下不能。特别是对于您的示例中的简短内联非虚拟函数(您需要将 foobar 标记为内联以与第一段代码完全等效),任何一种情况下的函数调用都可能简单地消失。

【讨论】:

  • 据我所知,编译器也可能内联大多数短的非内联甚至虚函数(当实际类型已知时)。这些编译器现在是聪明的野兽:)
  • @7vies:是的。 :) 主要要求是启用链接时优化(或实现调用它的任何内容),或者该定义在该 TU 中是已知的。
  • 标记为内联并不意味着编译器会这样做。无论您是否标记,它很可能会与上述功能一起使用。
  • @CashCow:在多个 TU 中使用的函数中,只有在使用它们的每个 TU 中定义的内联函数。这就是 inline 的真正现代含义,也是我的意思。 (例如,我没有说编译器将始终内联函数调用。)
  • @Fred Nurk:我有点困惑。这是否意味着 static 函数现在也被称为内联函数?
【解决方案4】:

第一个例子在类 foo 的虚函数表中有 foo::bar。第二个没有。这使它更节省空间。由于 foobar 不是虚拟的,编译器可能在优化方面可以做更多的事情。

【讨论】:

  • 非虚方法不在 vtable 中。
猜你喜欢
  • 1970-01-01
  • 2011-05-17
  • 1970-01-01
  • 2021-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多