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比较器的一致,唯一的例外在于,前者是一元函数,而非二元函数。