C++必知必会之(20)STL函数对象

1、STL使我们能够轻松快捷地编写复杂的代码,既标准又高度优化:

std::vector<std::string> names;

//.....

std::sort( names.begin( ),  names.end( ) );


2、STL另一个优雅之处在于高度可配置。

在以上的代码中,使用string的小于(<)操作符对vector中的string元素进行排序,但在其他场合下,未必总有一个小于操作符可供使用,而且有时并不希望以升序方式进行排序。

class State {

   public:

       //.....

        int population ( ) const;

        float aveTempF( )  const;

        //.....

};


对于这种情形,STL一般允许我们指定一个替代的类似小于操作符的操作。这样的操作被称为“比较器”,因为它用于比较来比较两个值:

inline bool popLess( const State &a,  const State &b )

        {   return a.population( ) < b.population( );   }


拥有针对State的比较器之后,就可以用它进行排序了:

State union[50];

//.....

std::sort( union, union + 50,  popLess );       //按人口数进行排序


3、这里我们传递一个指向popLess函数的指针作为比较器(回忆一下,当一个函数名字作为参数进行传递时,函数名字会退化成一个指针,正如此处数组名字union退化为一个指向其首元素的指针那样)。

因为popLess作为函数指针进行传递,所以它在sort内无法被内联。如果希望得到快速的排序操作,这种做法只能让人感到遗憾了。


如果使用函数对象作为比较器,会好得多:

struct PopLess : public std::binary_function<State, State, bool>    {

      bool operator ( )  ( const State &a,  const State &b )  const

          {    return popLess(a, b );   }

};

PopLess类型是一个典型的、有着正确构造的STL函数对象的例子。


首先,它是一个函数对象。它重载了函数调用操作符,因此可以以普通函数调用的语法调用。

这一点很重要,因为诸如sort这样的STL泛型算法是以这种方式编写的:函数指针和函数对象都可以用来实例化它们,只要此二者可以采用典型的函数调用语法进行调用即可。

一个具有重载的operator( )的函数对象完全满足这个语法要求。


其次,它派生于标准的binary_function基类。此项机制允许其他部分的STL实现询问函数对象编译器问题。

在这个例子中,从binary_function派生下来的PopLess类型允许我们找出函数对象的参数和返回值类型。


第三,这个函数对象没有数据成员、没有虚函数、没有显式声明的构造函数和析构函数,且对operator( )的实现是内联的。当于STL协调使用时,在函数对象中避免使用数据成员的一个原因在于,STL实现可能会为一个函数对象产生若干份复制,而且假定所有这些复制都是一致的。为了确保一个对象的所有复制一致,最简单的方式就是不要让对象带有任何数据成员。


现在我们使用该函数对象对这个union进行排序:

sort( union, union+50, PopLess ( )  );


4、注意,在这个sort调用中跟在PopLess后面的圆括号。

PopLess是一个类型,但是我们必须传入一个该类型的对象作为函数的参数。

通过在PopLess类型名字后面附加一对圆括号,就创建了一个没名字的临时PopLess对象,此对象仅存活于函数调用期间(即匿名临时对象)。也可以声明并传入一个具名对象:

PopLess comp;

sort ( union, union+50, comp );


5、使用函数对象作为比较器还有一个额外的好处,就是比较操作将被内联处理,而使用函数指针则不允许内联。

原因在于,当一个sort函数模版实例化时,编译器知道比较器的类型是PopLess,从而使它知道PopLess::operator( )将被调用,接着使用它可以内联该函数,最后使它可以内联对嵌套的popLess函数的调用!


6、在STL中,函数对象另一个常见的用途是用作判断式。

判断式是一个询问关于单个对象的真/假问题的操作(可以将比较器视作一种二元判断式)。

struct IsWarm : public std::unary_function<State, bool>   {

      bool operator ( ) ( const State &a ) const

           {   return a.aveTempF( ) > 60;   }

};


7、STL判断式的设计指导方针与STL比较器的一致,唯一的例外在于,前者是一元函数,而非二元函数。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值