您的位置:首页 > 编程语言 > C语言/C++

C++ STL 学习 :for_each与仿函数(functor)(一)

2015-03-12 15:02 387 查看
C++ STL 学习 :for_each与仿函数(functor)(一)
摘自网络

作者: zieckey  时间: 2010-07-20 13:38:00

先看wikipedia定义:

A function object, also called a functor, functional, or functionoid,[1]  is a computer programming construct allowing an object to be invoked or called like it was an ordinary function, usually with the same syntax.

简单来将,仿函数(functor)就是一个重载了"()"运算符的struct或class,利用对象支持operator()的特性,来达到模拟函数调用效果的技术。
我们平时对一个集合类遍历的时候,例如vector,是这样做的:

for(vector<int>::const_iterator iter = ivec.begin(); iter != ivec.end(); ++iter)

{

    //do your whatever you want here

}
例如下面的代码:
#include
<vector>
#include
<iostream>

struct State
{

    State( int state
) : m_state( state
){}

    ~State()
{ std::cout
<<
"~State(), m_state=" << m_state
<<
std::endl;
}

    void setState(
int state ){ m_state
= state;
}

    int getState()
const{
return m_state;
}

    void print()
const {
std::cout
<<
"State::print: " << m_state
<<
std::endl;
}

private:

    int m_state;
};

int main()
{

    std::vector<State*>
vect;

    vect.push_back(
new State(0)
);

    vect.push_back(
new State(1)
);

    vect.push_back(
new State(2)
);

    vect.push_back(
new State(3)
);

       std::vector<State*>::iterator
it( vect.begin()
);

    std::vector<State*>::iterator
ite( vect.end()
);

    for (
; it != ite;
++it
)

    {

        (*it)->print();

    }

    

    

    system(
"pause" );
4000

    return 0;
}

这里的for循环语句有点冗余,想到了std::for_each ,为了使用for_each,我们需要定义一个函数,如下:

void print( State* pstate )

{

    pstate->print();

}

于是就可以简化为下面代码:

std::for_each( vect.begin(), vect.end(), &print );

上面这段代码有点丑陋,看起来不太爽,主要是函数指针的原因。

在这种应用环境下,C++有仿函数来替代,我们定义一个仿函数,如下:

struct Printer

{

    template<typename T> void operator()( T* t ) { t->print(); }

};

于是就可以简化为下面代码:

std::for_each( vect.begin(), vect.end(), Printer() );

下面,我们初步看下 for_each 的STL源码实现: 

        // TEMPLATE FUNCTION for_each

template<class _InIt,

    class _Fn1>
inline

    _Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)

    {    // perform function for each element

    _DEBUG_RANGE(_First, _Last);

    _DEBUG_POINTER(_Func);

    _CHECKED_BASE_TYPE(_InIt) _ChkFirst(_CHECKED_BASE(_First));

    _CHECKED_BASE_TYPE(_InIt) _ChkLast(_CHECKED_BASE(_Last));

    for (; _ChkFirst
!= _ChkLast;
++_ChkFirst)

        _Func(*_ChkFirst);

    return (_Func);

    }

    

上面的代码看起来挺晕菜的,这里给出 effective STL 里面的一个实现,简单明了:

template<
typename InputIterator,
typename Function >

Function for_each( InputIterator beg, InputIterator end, Function f
) {

    while ( beg
!= end
)

        f( *beg++
);
}

其实for_each就是一个模板函数,将for循环语句封装起来,前面两个参数都是迭代器,第三个参数是使用一个函数指针(或仿函数),

其功能是对每一个迭代器所指向的值调用仿函数。之前觉得for_each挺神秘的,其实看看源码也挺简单的。呵呵。

上面代码还是有点冗余,因为为了使用for_each还要单独定义一个函数(或仿函数),不太清爽,

呵呵,stl早为我们准备好了 mem_fun 模板函数来解决这个一个问题,于是代码再次简化为:

std::for_each( vect.begin(), vect.end(), std::mem_fun( &State::print ) );

我们一起看看 mem_fun 的STL源码实现: 

        // TEMPLATE FUNCTION mem_fun
template<class _Result,

    class _Ty>
inline

    mem_fun_t<_Result, _Ty>
mem_fun(_Result
(_Ty::*_Pm)())

    {    // return a mem_fun_t functor adapter

    return (std::mem_fun_t<_Result,
_Ty>(_Pm));

    }

mem_fun 函数实际上是调用 mem_fun_t 函数,我们接着深入看看 mem_fun_t,

        // TEMPLATE CLASS mem_fun_t
template<class _Result,

    class _Ty>

    class mem_fun_t

        : public
unary_function<_Ty
*, _Result>

    {    // functor adapter (*p->*pfunc)(), non-const *pfunc
public:

    explicit mem_fun_t(_Result
(_Ty::*_Pm)())

        : _Pmemfun(_Pm)

        {    // construct from pointer

        }

    _Result operator()(_Ty
*_Pleft)
const

        {    // call function

        return ((_Pleft->*_Pmemfun)());

        }
private:

    _Result (_Ty::*_Pmemfun)();    //
the member function pointer

    };

将上面这段代码定义的写的我们好看懂一点,如下:

        // TEMPLATE CLASS mem_fun_t
template<
typename _Result,
typename _Ty >
class mem_fun_t
: public
unary_function<_Ty
*, _Result>
{    

    typedef _Result
(_Ty::*_Pmemfun)();
public:

    explicit mem_fun_t( _Pmemfun& pfunc
)

        : m_pfun( pfunc
)

    {    // construct from pointer

    }

    _Result operator()(_Ty
*_Pleft)
const

    {    // call function

        return (
(_Pleft->*m_pfun)()
);

    }

private:

    _Pmemfun m_pfun;
// the member function pointer

};

这样就比较清晰了,定义了仿函数mem_fun_t内部定义了一个类成员函数指针,

仿函数构造的时候将函数指针保存起来,当仿函数operator()被调用的时候,

就通过与一个类的实例关联起来从而实现了类成员函数的调用。

其调用流程是这样的,for_each把vector中的元素传送给mem_fun,

mem_fun自己产生一个仿函数mem_fun_t,然后仿函数调用其重载的()。

上述源码还有最后一个没有说明,就是unary_function,直接上源码:

        // TEMPLATE STRUCT unary_function
template<class _Arg,

    class _Result>

    struct unary_function

    {    // base class for unary functions

    typedef _Arg argument_type;

    typedef _Result result_type;

    };

就一个模板结构体。没有数据成员,非常简单。

最后,定义一个删除指针的仿函数:

struct DeletePointer

{

    template<typename T> void operator()( T* ptr ) const { delete ptr; }

};

d726

然后调用,就一个逐一删除vector里面的所有元素了。

std::for_each( vect.begin(), vect.end(), DeletePointer() );

源码:

 

#include
<vector>
#include
<iostream>
#include
<algorithm>
#include
<functional>

struct State
{

    State( int state
) : m_state( state
){}

    ~State()
{ std::cout
<<
"~State(), m_state=" << m_state
<<
std::endl;
}

    void setState(
int state ){ m_state
= state;
}

    int getState()
const{
return m_state;
}

    void print()
const {
std::cout
<<
"State::print: " << m_state
<<
std::endl;
}
private:

    int m_state;
};

void print( State* pstate
)
{

    pstate->print();
}

struct Printer
{

    template<typename T>
void operator()( T* t
) { t->print();
}
};

struct DeletePointer
{

    template<typename T>
void operator()( T* ptr
) const
{ delete ptr;
}
};

int main()
{

    std::vector<State*>
vect;

    vect.push_back(
new State(0)
);

    vect.push_back(
new State(1)
);

    vect.push_back(
new State(2)
);

    vect.push_back(
new State(3)
);

    std::vector<State*>::iterator
it( vect.begin()
);

    std::vector<State*>::iterator
ite( vect.end()
);

    for (
; it != ite;
++it
)

    {

        (*it)->print();

    }

    std::for_each( vect.begin(),
vect.end(),
&print );

    std::for_each( vect.begin(),
vect.end(), Printer()
);

    std::for_each( vect.begin(),
vect.end(),
std::mem_fun(
&State::print
) );

    std::for_each( vect.begin(),
vect.end(), DeletePointer()
);

    vect.clear();

    system(
"pause" );

    return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: