在C++中,编译器"内联"一个函数对象意味着什么?

Mon*_*urd 15 c++ functor function-object

在wikipedia 关于函数对象的文章中,它说这些对象在与for_each一起使用时具有性能优势,因为编译器可以"内联"它们.

我对这在这种情况下的意义有点模糊......或者我不好意思说的任何背景.谢谢你的帮助!

AnT*_*AnT 14

for_each模板的最后一个参数是仿函数.Functor是可以使用()运算符(可能带参数)"调用"的东西.根据定义,有两种不同的仿函数:

  1. 普通的非会员功能是仿函数.
  2. 具有重载()运算符的类类型的对象(所谓的函数对象)也是仿函数.

现在,如果你想使用普通函数作为函子for_each,它看起来像下面这样

inline void do_something(int &i) { /* do something */ }

int main() {
  int array[10];
  std::for_each(array, array + 10, &do_something);
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,for_each模板使用[推导]参数进行实例化<int *, void (*)(int &)>.请注意,在这种情况下,实际的函子值是&do_something作为函数参数传递的函数指针.从功能的角度来看,for_each这是一个运行时值.由于它是一个运行时值,因此无法内联对仿函数的调用.(就像通常情况下不可能内联通过函数指针进行的任何调用一样).

但是,如果我们使用函数对象,代码可能如下所示

struct do_something {
  void operator()(int &i) { /* do something */ }
}; 

int main() {
  int array[10];
  std::for_each(array, array + 10, do_something());
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,for_each模板使用[推导]参数进行实例化<int *, do_something>.从内部对仿函数的调用for_each将被引导至do_something::operator().调用的目标是已知的,并在编译时修复.由于目标函数在编译时是已知的,因此可以很容易地内联调用.

在后一种情况下,我们当然也有一个作为参数传递的运行时值for_each.它是do_something我们调用时创建的[可能是"虚拟"临时] 类的实例for_each.但是此运行时值对调用的目标没有影响(除非operator ()是虚拟的),因此它不会影响内联.

  • @Omnifarious:在我的例子中,您可以使用具有`void(int&)`签名的不同函数调用`for_each`,并且编译器被强制使用`for_each`的相同的,唯一的实例化:`for_each <int*,void (*)(INT&)`.即编译器*required*每次使用相同的`for_each`实例,并执行对`do_something`函数的间接调用.当然,如你所说,智能编译器可以找到一种方法来静静地创建`for_each`的几个中断,但是在一般情况下,这将是一个相当可疑的事情. (2认同)
  • 例如(忘记模板),当我在程序中使用函数`void foo(int)`并多次调用它作为`foo(1); FOO(2); foo(3);`我通常希望编译器为`foo`生成一个函数体,并使用不同的参数执行相同的主体:1,2和3.如果我发现编译器生成了3个不同的`foo体`分别用"内联"常数1,2和3,我会感到非常惊讶.对于小的`foo`来说可以(如果它在那之后被内联),但对于更大的`foo`,这是不可取的.你所描述的基本上是一回事. (2认同)

Cha*_*tie 7

内联是编译器可以用函数本身的内容替换对函数的调用的过程.它要求编译器在编译时知道函数的内容.

如果传递函数指针,编译器通常不能这样做.