使用STL算法,传递函数指针还是函子更好?

发布于 2024-07-25 02:28:18 字数 330 浏览 6 评论 0原文

这 2 种方法哪一种更好,为什么?

方法1:

void fun(int i) {
  //do stuff
}

...
for_each(a.begin(), a.end(), fun);

方法2:

class functor {
public:
  void operator()(int i);
};

...
for_each(a.begin(), a.end(), functor());

编辑: 应该这样表述,在什么情况下上述方法之一优于另一种方法?

多谢!

Which of these 2 methods is better and why?

Method 1:

void fun(int i) {
  //do stuff
}

...
for_each(a.begin(), a.end(), fun);

Method 2:

class functor {
public:
  void operator()(int i);
};

...
for_each(a.begin(), a.end(), functor());

Edit: Should have formulated it this way, in what situation is one of the above method preferable to the other?

Thanks a lot!

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

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

发布评论

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

评论(6

暮光沉寂 2024-08-01 02:28:18

函子可能(并且将会)被简单地内联——这对于常规函数指针来说不是这样做的。

因此,函子具有真正的性能优势,这在紧密循环中可能是巨大的。 此外,函子通常更容易组合,特别是与 STL 配合得更好:std::bindx 不适用于函数指针, 例如。

我讨厌它们使代码变得混乱,但考虑到它们的所有优点,我任何时候都更喜欢它们而不是函数指针。

Functors may (and will) be trivially inlined – this isn't done for regular function pointers.

Thus, functors have a real performance benefit which may be huge in tight loops. Furthermore, functors are generally more easily composable and in particuler play nicer with the STL: std::bindx doesn't work on function pointers, for instance.

I hate how they clutter the code but given all the advantages, I'd prefer them over function pointers any time.

水波映月 2024-08-01 02:28:18

为了消除对编译器可以内联什么的误解,足够好的编译器可以内联函数指针。 由于有更多可用的静态信息,它可以更轻松地内联函数对象。 例如,指向不带参数并返回 bool 的函数的指针的类型为 bool (*)(),而函子有显式类型,即函子,并且模板实例化可以静态调用函子运算符,而不是而不是必须通过函数指针调用。

但在实践中,主要是为编译器提供足够的信息来有效优化。

例如,对于 Visual C++ 2008,给定以下经过完全优化的代码:

#include "stdafx.h"
#include <algorithm>

const char print_me[]= "hello!";

class print_functor
{
public:
    void operator()(char c)
    {
        printf("%c", c);
    }
};

void print_function(char c)
{
    printf("%c", c);
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::for_each(print_me, print_me + sizeof(print_me)/sizeof(print_me[0]), print_functor());
    printf("\n");

    std::for_each(print_me, print_me + sizeof(print_me)/sizeof(print_me[0]), print_function);

    return 0;
}

完全内联两个 std::for_each 调用。 顺便说一句,在 PC 上,第一个 for_each 有一个不必要的 lea ecx, [ecx]

To clear up a misconception of what a compiler can inline, a good enough compiler can inline function pointers. It can just inline function objects more easily since there is more static information available. E.g., a pointer to a function that takes no parameters and returns a bool is of type bool (*)(), while a functor has an explicit type, namely, the functor, and the template instantiation can statically call the functor operator, rather than having to call through a function pointer.

In practice, though, it's mainly a matter of giving the compiler enough information to optimize effectively.

For example, Visual C++ 2008, given the following code with full optimizations:

#include "stdafx.h"
#include <algorithm>

const char print_me[]= "hello!";

class print_functor
{
public:
    void operator()(char c)
    {
        printf("%c", c);
    }
};

void print_function(char c)
{
    printf("%c", c);
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::for_each(print_me, print_me + sizeof(print_me)/sizeof(print_me[0]), print_functor());
    printf("\n");

    std::for_each(print_me, print_me + sizeof(print_me)/sizeof(print_me[0]), print_function);

    return 0;
}

inlines both std::for_each calls completely. Incidentally, on the PC, the first for_each has an unnecessary lea ecx, [ecx].

空气里的味道 2024-08-01 02:28:18

与函数指针相比​​,函数对象的一大优点是您可以在函数对象构造时更轻松地绑定一些参数。

可以执行此操作的函子的一个示例是,

  class multiplyBy
  {
  private:
      int m_whatToMultiplyBy;
  public:
      multiplyBy(int whatToMultiplyBy) : 
          m_whatToMultiplyBy(whatToMultiplyBy)
      {
      }

      void operator()(int& i)
      {
          i = m_whatToMultiplyBy * i;
      }
  }


  ...

  // double the array
  for_each(a.begin(), a.end(), multiplyBy(2));

可以使用 boost::bindboost::function 如果您可以使用 boost。

One big advantage of a function object over a function pointer is that you can more easily bind up some arguments at function object construction.

An example of a functor that might do this would be

  class multiplyBy
  {
  private:
      int m_whatToMultiplyBy;
  public:
      multiplyBy(int whatToMultiplyBy) : 
          m_whatToMultiplyBy(whatToMultiplyBy)
      {
      }

      void operator()(int& i)
      {
          i = m_whatToMultiplyBy * i;
      }
  }


  ...

  // double the array
  for_each(a.begin(), a.end(), multiplyBy(2));

This "binding" of arguments can be done quite nicely with boost::bind and boost::function if boost is available to you.

墨小沫ゞ 2024-08-01 02:28:18

我的意见 - #1 更好,因为它更简单。

仅仅因为某物可以是一个对象,并不意味着它应该是一个对象。 我确信在某些情况下函子是有意义的,但在大多数情况下可能不需要它。

My opinion - #1 is better, because it's simpler.

Just because something can be an object, doesn't mean it should be one. I'm sure there are cases where the functor makes sense, but in most cases there's probably no need for it.

我一向站在原地 2024-08-01 02:28:18

函子可以更容易内联,因此它可能是性能时需要考虑的一个因素很重要。

A functor can be more easily inlined, so it may be a factor to consider when performance is important.

颜漓半夏 2024-08-01 02:28:18

#1 函数声明更简单
而#2 函子看起来更像是函数调用。

(有时你不得不对c++语法感到绝望)

#1 is simpler to declare the function
while #2 the functor looks more like a function call.

(Sometime you have to despair of c++ syntax)

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