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

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

2013-11-25 12:36 218 查看
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比较器的一致,唯一的例外在于,前者是一元函数,而非二元函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: