STL 之迭代函数解析

    技术2022-05-12  21

    STL包含了用于迭代容器中元素的方法-迭代方法,包括for_each, transform, copy, find, remove

    1、用法:

    //模板函数,打印元素 template<class _T> void print(_T arg) { cout << arg << " "; } //模板函数,对给定元素取反 template<class _T> _T negative(_T arg) { return -(arg); } vector<int> days; vector<int> days; for (int i = 1; i <= 7; i++) { days.push_back(i); } //打印容器中的元素 for_each(days.begin(), days.end(), print<int>); //对容器中的元素取反 transform(days.begin(), days.end(), days.begin(), negative<int>);

     

    2、细节部分

    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 for (; _ChkFirst != _ChkLast; ++_ChkFirst) _Func(*_ChkFirst); return (_Func); }

    可以看到,通过迭代容器中的元素,将每个元素作为参数,调用第三个参数(函数指针,注意这里的函数是全局函数)

     

    3、对类成员函数的调用,STL函数适配器

    如for_each代码所示,只能调用全局函数(ordinary functions)或者函数对象(function objects,请参考STL关于函数对象的描述),那么要对容器中的对象,调用其成员函数,要怎么办呢? 这里STL提供了一种设计方法:适配器(适配器,是一种将两个不能直接交流的物件进行中介的一种中间人,这也是设计里面的一种模式)。

    STL提供的适配器包括 ptr_fun, mem_fun, mem_fun_ref。

    a) ptr_fun是一个模板函数,返回一个函数对象,该适配器可适配普通函数(ordinary function),请看下面STL关于ptr_fun相关的代码:

    //_Arg是待调用函数的参数类型,_Result是待调用函数的返回值类型。 //pointer_to_unary_function是一个函数对象(function object) //ptr_fun的参数是一个函数指针,返回一个pointer_to_unary_function函数对象的实例,该实例可以被for_each调用 template<class _Arg, class _Result> inline pointer_to_unary_function<_Arg, _Result, _Result (__cdecl *)(_Arg)> ptr_fun(_Result (__cdecl *_Left)(_Arg)) { // return pointer_to_unary_function functor adapter return (std::pointer_to_unary_function<_Arg, _Result, _Result (__cdecl *)(_Arg)>(_Left)); }

     

    现在在看一下pointer_to_unary_function的代码,就知道整个调用过程是怎样进行的了:

    // 这是一个模板类,保存通过构造函数传递进来的函数指针,重载()运算符,调用()时,转换为对函数指针的调用 // TEMPLATE CLASS pointer_to_unary_function template<class _Arg, class _Result, class _Fn = _Result (*)(_Arg)> class pointer_to_unary_function : public unary_function<_Arg, _Result> { // functor adapter (*pfunc)(left) public: explicit pointer_to_unary_function(_Fn _Left) : _Pfun(_Left) { // construct from pointer } _Result operator()(_Arg _Left) const { // call function with operand return (_Pfun(_Left)); } protected: _Fn _Pfun; // the function pointer };

     注意下面的代码调用效果一样:

    for_each(days.begin(), days.end(), print<int>); for_each(days.begin(), days.end(), ptr_fun(print<int>));

    ptr_fun为需要对象函数的方法提供适配,例如如下代码:

    //find first workingday bool isWorkingday(int day) { return day >=1 && day <=5; } //找到第一个工作日 vector<int>::iterator pos = find_if (days.begin(), days.end(), isWorkingday); /* pos = find_if (days.begin(), days.end(), not1(isWorkingday)); // 该调用会出现编译错误 */ //not1是一个函数对象,构造函数也需要一个函数对象,正确的方法如下: //找到第一个非工作日 pos = find_if (days.begin(), days.end(), not1(ptr_fun(isWorkingday)));

     

    b) mem_fun, 该适配器提供对对象成员函数的调用, 参考一下STL的实现代码:

    // 模板类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 }; // 模板函数mem_fun,返回一个函数对象 // 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)); }

    c) mem_fun_ref, 含义和mem_fun相同, 区别在于mem_fun通过对象指针调用,mem_fun_ref通过对象引用调用, 参考以下STL实现代码:

    // 模板类,重载(),调用()时,为指定对象调用类的成员函数 // TEMPLATE CLASS mem_fun_ref_t template<class _Result, class _Ty> class mem_fun_ref_t : public unary_function<_Ty, _Result> { // functor adapter (*left.*pfunc)(), non-const *pfunc public: explicit mem_fun_ref_t(_Result (_Ty::*_Pm)()) : _Pmemfun(_Pm) { // construct from pointer } _Result operator()(_Ty& _Left) const { // call function return ((_Left.*_Pmemfun)()); } private: _Result (_Ty::*_Pmemfun)(); // the member function pointer }; // 模板函数mem_fun_ref, 返回一个函数对象 // TEMPLATE FUNCTION mem_fun_ref template<class _Result, class _Ty> inline mem_fun_ref_t<_Result, _Ty> mem_fun_ref(_Result (_Ty::*_Pm)()) { // return a mem_fun_ref_t functor adapter return (std::mem_fun_ref_t<_Result, _Ty>(_Pm)); }

     

    从mem_fun, mem_fun_ref可以学习到如何在对象外部,通过对象指针和对象引用,调用指定类的成员方法。

    最后注意:mem_fun用于指针的容器(支持多态的),mem_fun_ref用于对象的容器。


    最新回复(0)