关于函数对象

rhesus 2003-11-04 10:15:08
到底用函数对象和函数指针有什么区别?
C++primer上说函数指针的缺点是他的间接应用使其不能被内联(不解其义)
...全文
436 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
ntxs 2003-11-18
  • 打赏
  • 举报
回复
up
eastsun 2003-11-07
  • 打赏
  • 举报
回复


函数对象大约相当于数学中的算子。

而函数指针就是指向某函数的指针。

函数对象一般是将( )(其中可以不带参数或者带若干个参数)进行了重载。

FOR EXAMPLE。

class _functor
{
public:
_functor( );
virtual ~_functor( );

public:
double operator ( ) ( double dX );
};

void TestFunctor( )
{
_functor temp_functor;
double bValue = temp_functor( 3.0 );
}
Wolf0403 2003-11-05
  • 打赏
  • 举报
回复
Function几乎是任何语言的元素之一,从Pascal,Fortran到C++,VB,几乎任何时代的语言都支持它。在C++里,随着 C++标准库的推出,人们开始渐渐的接触到另一种定义函数的方式:Functor。所谓Functor,其实就是重载了operator () 的类,其使用方式和普通函数差不多(这正是C++处处体现的一种思想:只在定义上有区别,在使用上毫无区别)。
  譬如说,如果我们要定义一个函数,将传入的整型引用加一,我们可以有两种方法定义:
inline void increase_one_func(int& i)
{
  ++i;
}
class increase_one_functor
{
public:
  void operator()(int& i)
  {
    ++i;
  }
}
increase_one_functor;
使用起来则没什么区别:
int i=0;
increase_one_func(i);
increase_one_functor(i);

  那Function和Functor到底有什么区别呢?其实他们定义方式的区别已经决定了他们使用上的区别了。

  首先,Functor相比Function来说,可以传递更多的信息:
因为Functor是以类的方式存在的,它可以包含任意多的信息。除了传入参数以外,你还可以在类内预设一些其它的信息。
譬如说,下面这个Functor:
class increase_one_functor
{
  int mIncrement;
public:
  increase_one_functor(int increment=1):mIncrement(increment)
  {}
  void operator()(int& i)
  {
    ++i;
  }
}
  可以很方便的实现将一个整数增加任意值的功能:
increase_one_functor(100)(i);// 将i加100。
  而Function就很难实现这样的可扩展性。

  其次,在作为参数传递时,Functor的效率往往比Function要高。这是因为,在把Functor作为参数传递时,你实际上传递的是Functor对象,在整个编译过程中,编译器始终知道它所在处理的Functor对象是哪个Functor类的,也就是说,它可以做编译时的优化。而对于Function来说,它往往以指针的方式传递,对于编译器来说,很难做(并不是不可能)编译时的优化。
  下面这段程序或许可以说明问题:
#include <windows.h>
#include <iostream>

using namespace std;

inline void increase_one_func(int& i)
{
  ++i;
}

class increase_one_functor
{
public:
  void operator()(int& i)
  {
    ++i;
  }
}
increase_one_functor;

const int VECTOR_SIZE=1024*16;

void treat_vector_func(int ai[VECTOR_SIZE],void (*func)(int& i))
{
  for(int i=0;i<VECTOR_SIZE;++i)
    func(ai[i]);
}

template<typename T>
void treat_vector_func(int ai[VECTOR_SIZE],T functor)
{
  for(int i=0;i<VECTOR_SIZE;++i)
    functor(ai[i]);
}

void main(void)
{
  static int ai[VECTOR_SIZE];
  const int CALL_TIMES=10240;
  {
    long l=GetTickCount();
    for(int i=0;i<CALL_TIMES;++i)
      treat_vector_func(ai,increase_one_func);
    l=GetTickCount()-l;
    cerr<<"function "<<l<<endl;
  }
  {
    long l=GetTickCount();
    for(int i=0;i<CALL_TIMES;++i)
      treat_vector_func(ai,increase_one_functor);
    l=GetTickCount()-l;
    cerr<<"functor "<<l<<endl;
  }
}
  运行结果如下:
  Debug模式下(也就是说,没有任何优化的情况下):
function 37623
functor 36825
Release模式下:
function 4573
functor 1726
  可见,functor比function要快很多。


——以上转自 AllAboutProgramming 论坛
Robin 2003-11-05
  • 打赏
  • 举报
回复
挺复杂的,不是三言两语可以讲明白的!
Robin 2003-11-05
  • 打赏
  • 举报
回复
那是一种设计模式!用来降低对象之间的联系(decoupled interobject communication)!
是一种将请求(request)存储在对象之中的的设计思路!
参看《Modern C++ Designe Generic Prigamming and Design Patterns Applied》!
或者设计模式Command!
短歌如风 2003-11-05
  • 打赏
  • 举报
回复
“他的间接应用使其不能被内联”这样说是正确的——正如bosedom的解释——但这还并不能成为他的缺点——至少不是什么了不得的缺点。并且这种说法只适用于“泛型函数对象”而不适用于“多态函数对象”。

使用函数指针实现"callback"的最大缺点是它没有状态,而对象则可以有状态。
比如一个排序函数,如果它要求用一个参数传入比较函数, 如果我们用函数对象,我们就可以轻易写一个对比较次数进行统计的函数对象来对这个排序进行分析。而函数指针则不行。
当然,用函数指针可以用全局变量来存放状态,但这个状态并不是它的,而是全局的,因此,一旦你用了这种方法:
1:你的函数不是线程安全的。
2:你的函数是不可重入的。
3:不但不可重入,在被两个任务交叉调用都会得到你意想不到的结果。

当然,用函数指针也可以通过修改接口加入“自定义数据指针”的方法来实现自己的状态(大量需要回调的系统API和库函数如pthread_create都用了这种方法),但这种方法其实是“面向对象的C实现”,它用“自定义数据”和“函数指针”一起实现了一个“多态函数对象”。
C++primer我没有看过,如果只说了函数对象的这个优点或是对这个优点比较看重的话,颇有“买椟还珠”之嫌。
panzhaoping 2003-11-05
  • 打赏
  • 举报
回复
同意
bosedom 2003-11-04
  • 打赏
  • 举报
回复
函数对象实际上是一个类的对象,不过在使用的时候可以直接使用类名。
函数指针因为是用了指针,所以在编译的时候不能向内联函数那样在调用地直接展开。需要一定的开销。
chinajiji 2003-11-04
  • 打赏
  • 举报
回复
function pointer:
A pointer to a function, its' value is the function's address.

function object:
A object to be used as a function, function's states can be presented as the function object's members.

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧