在 C++对于编译器来说“内联”意味着什么?函数对象?

发布于 2024-08-20 16:31:44 字数 240 浏览 11 评论 0原文

在维基百科关于函数对象的文章中说这些对象与for_each一起使用时具有性能优势,因为编译器可以“内联”它们。

我对这在这种情况下的确切含义有点模糊……或者在我不好意思说的任何情况下。感谢您的帮助!

In the wikipedia article about function objects it says such objects have performance advantages when used with for_each because the compiler can "inline" them.

I'm a bit foggy on exactly what this means in this context... or any context I'm embarrassed to say. Thanks for any help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

孤云独去闲 2024-08-27 16:31:44

for_each 模板的最后一个参数是一个函子。 函子是可以使用()运算符(可能带有参数)“调用”的东西。根据定义,有两种不同类型的函子:

  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);
}

在这种情况下,for_each 模板使用 [推导] 参数进行实例化。请注意,这种情况下的实际函子值是作为函数参数传递的函数指针&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());
}

在本例中,for_each 模板是使用[推导的]参数 实例化的。从 for_each 内部对函子的调用将被定向到 do_something::operator()。调用的目标是已知的并在编译时固定。由于目标函数在编译时已知,因此可以轻松内联调用。

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

The last parameter of for_each template is a functor. Functor is something that can be "called" using the () operator (possibly with arguments). By defintion, there are two distinctive kinds of functors:

  1. Ordinary non-member functions are
    functors.
  2. Objects of class type with overloaded () operator (so called function objects) are also functors.

Now, if you wanted to use an ordinary function as a functor for for_each, it would look something like the following

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

int main() {
  int array[10];
  std::for_each(array, array + 10, &do_something);
}

In this case the for_each template is instantiated with [deduced] arguments <int *, void (*)(int &)>. Note that the actual functor value in this case is the function pointer &do_something passed as the function argument. From the point of view of for_each function this is a run-time value. And since it is a run-time value, the calls to the functor cannot be inlined. (Just like it is in general case impossible to inline any call made through a function pointer).

But if we use a function object instead, the code might look as follows

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

int main() {
  int array[10];
  std::for_each(array, array + 10, do_something());
}

In this case the for_each template is instantiated with [deduced] arguments <int *, do_something>. The calls to the functor from inside for_each will be directed to do_something::operator(). The target for the call is known and fixed at compile-time. Since the target function is known at compile-time, the call can easily be inlined.

In the latter case we, of course, also have a run-time value passed as an argument to for_each. It is a [possibly "dummy" temporary] instance of do_something class we create when we call for_each. But this run-time value has no effect on the target for the call (unless the operator () is virtual), so it doesn't affect inlining.

浪漫人生路 2024-08-27 16:31:44

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

如果传递函数指针,编译器通常无法执行此操作。

Inline is the process a compiler can replace a call to a function with the contents of the function itself.
It requires the compiler to know the contents of the function when it's being compiled.

The compiler often can't do this if a function pointer is passed.

情话已封尘 2024-08-27 16:31:44

内联只是意味着直接用该函数的主体替换对该函数的每个调用。

这是对小函数的优化,因为它减少了跳转到新函数然后返回的开销。

Inlining just means replacing every call to that function with the body of that function directly.

It's an optimization for small functions because it reduces the overhead of jumping to a new function and then returning.

梅倚清风 2024-08-27 16:31:44

这意味着函数的定义(代码)可以被复制,从而使您免于函数调用(这在某些系统上被认为是昂贵的)。考虑宏替换。

It means that the function's definition (code) may be copied and saving you from a function call (which is considered to be expensive on some systems). Think of macro replacement.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文