STL中的函数对象

转载 2015年11月19日 15:17:00
  STL不但使我们能够更轻松、更快捷地编写复杂的代码,而且使编写的代码既标准又高度优化。
std::vector<std::string> names;
// ...
std::sort(names.begin(), names.end());
   STL另一个优雅之处在于高度可配置。在以上的代码中,使用string的小于(<)操作符对vector中的string元素进行排序,但在其它场合,未必总有一个小于操作符可供使用,而且有时并不希望以升序方式进行排序。
class State
{
public:
   // ...
   int population() const;
   float aveTempF() const;
   // ...
};
    State类用于表示联邦的一个州,它没有小于操作符,而且也不打算为它实现一个,因为“一个州小于另一个州”说不清是什么意思。幸运的是,对于这样的情形来说,STL一般允许我们指定一个替代的类似小于操作符(less-than-like)的操作。这样的操作被称为“比较器”,因为它用于比较两个值:
inline bool popLess(const State& a, const State& b)
{
     return a.population() < b.population();
}
拥有针对State的比较器之后,就可以用它进行排序了:
State aUnion[50];
// ...
std::sort(aUnion, aUnion + 50, popLess); // 按人口数进行排序
   这里我们传递一个指向popLess函数的指针作为比较器(函数名字会退化成一个指针)。因为popLess作为函数指针进行传递,所以它在sort内无法被内联。如果希望得到快速的排序操作,这种做法只能让人感到遗憾了。
   如果使用函数对象作为比较器,情况就会好很多:
struct PopLess : public std::binary_function<State, State, bool>
{
   bool operator () (const State& a, const State& b) const
   {
      return a.population() < b.population();
   }
};

   PopLess类型是一个典型的、有着正确构造的STL函数对象的例子。
   首先,它是一个函数对象。它重载了函数调用操作符,因此可以以普通函数调用的语法调用。这一点很重要,因为诸如sort这样的STL泛型算法是以这种方式编写的:函数指针和函数对象都可以用来实例化它们,只要此二者可以采用典型的函数调用语法进行调用即可。一个具有重载的operator()的函数对象完全可以满足这个语法要求。
   其次,它派生于标准的binary_function基类。此项机制允许其它部分的STL实现询问函数对象编译器问题。在这个例子中,从binary_function派生下来的PopLess类型允许我们找出函数对象的参数和返回值类型。不过在这里我们并没有利用这种能力,但是可以打赌肯定有人需要这样的能力,而且希望我们的PopLess类型可以为其他人所用。
   第三,这个函数对象没有数据成员、没有虚函数、没有显示声明的构造函数和析构函数,且对operator()的实现是内联的。用作STL比较器的函数对象一般都很小巧。简单且快速。当然可以设计一个具有重型实现的STL函数对象,但这种做法通常不是明智之举。当与STL协同使用时,在函数对象中避免(或尽量少)使用数据成员的另一个原因在于,STL实现可能为会一个函数对象产生若干份复制,而且假定所有这些复制都是一致的。为了确保一个对象的所有复制一致,最简单的方式就是不要让对象带有任何数据成员。
    现在我们就可以使用该函数对象对这个aUnion进行排序:
    std::sort(aUnion, aUnion + 50, PopLess());   // 按人口数进行排序
    请注意在这个sort调用中跟在PopLess后面的圆括号。PopLess是一个类型,但是我们必须传入一个该类型的对象作为函数的参数。通过在PopLess类型名字后面附加一对圆括号,就创建了一个没名字的临时PopLess对象,此对象仅存活于函数调用期间(这个没名字的对象即总所周知的“匿名临时对象”)。也可以声明并传入一个具名对象:
PopLess comp;
std::sort(aUnion, aUnion + 50, comp); // 按人口数进行排序
   然而,传入一个匿名临时对象更简单、更符合习惯,而且击键次数更少。
   使用函数对象作为比较器还有一个额外的好处,就是比较操作将被内联处理,而使用函数指针则不允许内联。原因在于,当一个sort函数模板实例化时,编译器知道比较器的类型是PopLess,从而使它知道PopLess:operator()将被调用,接着使它可以内联该函数。
   在STL中,函数对象另一个常见的用途是用作判断式。判断式是一个询问关于单个对象的真/假问题的操作(可以将比较器视作一种二元判断式)。
struct IsWarm : public std::unary_function<State, bool>
{
   bool operator () (const State& a) const
   {
      return a.aveTempF() > 60;
   }
};
   STL判断式的设计知道方针与STL比较器的一致,唯一的例外在于,前者是一元函数,而非二元函数。从我们前面排过序的State结果开始,采用一个适当的判断式,可以让我们很容易就能找到一个气候温暖且人数较少的州:
State* warmandsparse = find_if(aUnion, aUnion + 50, IsWarm());

STL算法和函数对象

STL算法和函数对象 #include 1. find() 在一个迭代器区间内查找一个特定元素,可以对任何类型容器的元素使用此算法。它会返回一个指示所找到元素的迭代器,或者是区间的末尾迭代器,可...
  • heyongluoyao8
  • heyongluoyao8
  • 2011年11月21日 22:10
  • 2055

STL算法设计理念 - 预定义函数对象

预定义函数对象基本概念:标准模板库STL提前定义了很多预定义函数对象 1)使用预定义函数对象: #include #include #include #include #include ...
  • zyq522376829
  • zyq522376829
  • 2015年07月09日 21:06
  • 926

STL的6大组件:容器、类属算法、迭代器、函数对象、适配器、分配器。

STL知识点。梗概。 ...
  • chenhu_doc
  • chenhu_doc
  • 2006年07月29日 22:19
  • 3050

STL函数对象:与函数指针的比较

一、函数对象、函数指针的定义和使用       二者定义方式不同,使用方式相同。 #include using namespace std; //function object class obj...
  • kanguolaikanguolaik
  • kanguolaikanguolaik
  • 2013年08月17日 08:29
  • 754

STL中的函数对象(一)

为使类属性算法具有灵活性,STL常用函数重载机制为算法提供两种形式,算法的第一种形式使用的是常规操作来实现目标。在第二种形式中,算法可以根据用户指定的准则对元素进行处理。这种准则是通过函数对象来传递的...
  • zz460833359
  • zz460833359
  • 2015年08月29日 10:23
  • 661

C++手稿:STL中的函数对象与函数指针

先来感受一下C++中的函数对象和函数指针: templatetypename T> void printer(int a, int b, T func){ coutfunc(a, b)e...
  • yangjvn
  • yangjvn
  • 2015年08月19日 11:05
  • 899

STL函数对象之预定义函数对象和函数对象绑定器

STL为我们定义了一些常用的函数对象,如下表。 函数绑定器是函数对象,它能结合函数对象、于特定值或函数在一起使用。它们也是被定义在 . 看下面的例子: find_if (coll.begin...
  • FlowShell
  • FlowShell
  • 2015年02月11日 14:57
  • 707

STL之函数对象

目录 为了使类属算法具有灵活性,STL常使用函数的重载机制为算法提供两种形式。算法的第一种形式使用的是常规的操作来实现。第二种形式中,算法可以根据用户指定的准测对元素经行处理。 函数对象包...
  • haifengzhilian
  • haifengzhilian
  • 2014年04月14日 17:20
  • 1012

面向对象的思考题

界面上有5个按钮,点击每个按钮会采取不同的结算订单方式,如买二增一,折后满50免运费,打8折,满200返100,满300打六折。 1.(初级)请使用面向过程的思想设计此应用,写出你的思路。 2.(中级...
  • zjq2008wd
  • zjq2008wd
  • 2013年11月19日 13:56
  • 908

C++ STL 基础及应用(7) 函数对象(仿函数)

把函数作为对象是程序设计的新思维。STL 通过重载类中的 operator() 函数实现函数对象功能,不但可以对容器中的数据进行各种各样的操作,而且能够维护自己的状态。因此,与标准 C 库函数相比,函...
  • Raito__
  • Raito__
  • 2016年06月08日 14:39
  • 2148
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:STL中的函数对象
举报原因:
原因补充:

(最多只允许输入30个字)