effective stl 第41条:理解ptr_fun/mem_fun/mem_fun_ref的由来

来源:互联网 发布:身份证阅读器软件下载 编辑:程序博客网 时间:2024/05/18 11:27

这三个函数的主要作用是掩盖C++语言中一个内在的语法不一致的问题。

#include<iostream>#include<vector>#include<list>#include<algorithm>using namespace std;class Widgets{public:    Widgets(){};    void test(){};private:};//假设是一个可以测试widgets的对象void test(const Widgets& w){}int main(){    //存放widget的容器    vector<Widgets> vW;    //测试vW中的每一个 Widget对象    for_each(vW.begin(), vW.end(), test);//#1,可以通过编译    //假设test是Widget的成员对象    for_each(vW.begin(), vW.end(), &Widgets::test);//#2,不能通过编译    list<Widgets*> lpw;    for_each(lpw.begin(), lpw.end(), &Widgets::test);//#3,不能通过编译    return 0;}

通过查看STL想用的源代码,我们发现,我们只有一个for_each的算法。

        // TEMPLATE FUNCTION for_eachtemplate<class _InIt,    class _Fn1> inline    void _For_each(_InIt _First, _InIt _Last, _Fn1& _Func)    {   // perform function for each element    for (; _First != _Last; ++_First)        _Func(*_First);    }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);    _For_each(_Unchecked(_First), _Unchecked(_Last), _Func);    return (_STD move(_Func));    }

上边的代码很明显的表示for_each的实现是基于使用语法#1的。这是STL中一个很普遍的惯例:函数或者函数对象在被调用时,总是使用非成员函数的语法形式。

现在mem_fun和mem_fun_ref之所以必须存在的原因已经很清楚了——他们被用来调整成员函数,使之能通过语法#1被调用。

#include<iostream>#include<vector>#include<list>#include<algorithm>#include<functional>using namespace std;class Widgets{public:    Widgets(){};    void test(){};//执行自测,如果不通过,则将*this标记为失败private:};//假设是一个可以测试widgets的对象void test(const Widgets& w){}int main(){    //存放widget的容器    vector<Widgets> vW;    //测试vW中的每一个 Widgets对象    for_each(vW.begin(), vW.end(), test);//#1,可以通过编译    //假设test是Widgets的成员对象    for_each(vW.begin(), vW.end(), mem_fun_ref(&Widgets::test));//#2,不能通过编译    list<Widgets*> lpw;    for_each(lpw.begin(), lpw.end(), mem_fun(&Widgets::test));//#3,不能通过编译    return 0;}

如果你不知道什么时候使用ptr_fun,什么时候不使用ptr_fun,那么你可以每次将一个函数传给一个STL的组件时总是使用它。stl不会在意,而且这样做不会带来性能的损失。另一种策略是,只有在迫不得已的时候使用,如果你省略了那些必要的类型定义,编译器会提醒你。然后再把ptr_fun加上去。

0 0
原创粉丝点击