程序员通常以下面4种形式使用仿函数:
1)作为排序规则。
2)拥有内部状态。
4)作为判断式。
1.仿函数作为排序规则
仿函数可以将已序的数据放入容器中。使用通常的运算符“operator<”有时不能对这些元素排序,因此需要自定义特别的规则来实现排序的目的,而仿函数可以作为排序规则,详见例13-1。
例13-1
例13-1的执行结果为:
例13-1使用了仿函数类person_sort_rule。该类定义了operator()函数。该函数对输入的数据的lastname字段进行比较。所有元素以此作为排序规则进行排序。若以一般的函数作为排序规则,则比较困难。由于set具有自动排序性,这是不能避免的,但程序员可以设计自己的排序规则。
2.仿函数可以拥有内部状态
仿函数还可以使程序在同一时刻拥有多个状态。函数传递数值的方式也有两种:通过值传递;通过引用传递。仿函数是采用第一种方式:值传递。算法并不会改变随参数而来的仿函数的状态。仿函数参数采用“传递值”方式的好处是可以传递常量或临时表达式;缺陷是无法改变仿函数的状态。算法可以改变仿函数的状态,但无法存取或改变其最终状态,改变的仅仅是仿函数的副本。有时需要存取最终状态,其关键是怎样从算法中获取结果。
从使用仿函数的算法中获取结果或反馈的方法通常有两种:
1)以引用的方式传递仿函数。若希望能够以引用的方式传递仿函数,则需要在调用算法时明确表示仿函数型别是引用型别。
2)使用for_each()算法的返回值。
下面以例13-2来说明上述知识点。
例13-2
例13-2的执行结果为:(www.xing528.com)
本例是以仿函数产生一个整数序列。当仿函数的运算符operator()被调用时,函数会返回整数值并累加1。可通过构造函数的参数指定初始值。例13-2还使用了generate()和gen-erate_n()算法。这两个算法的作用是:产生数值用以写入群集内。在使用仿函数sequence()时,均使用了初始参数,该初始参数可作为产生序列的初始值。算法generator_n()会连续n次改写元素值,产生n个元素。例如,
上述语句会产生以42为起始值的整数序列。
通过修改operator()可以产生更加复杂的序列。例如,
上述程序的执行结果为:
若要实现以引用的方式传递函数,读者可将例13-2修改为例13-3。
例13-3
例13-3的执行结果为:
3.算法for_each()的返回值
若使用算法for_each(),则不必实例化仿函数的“引用计数版本”来存取最终状态。算法for_each()有其独门绝技,这是其他算法所没有的,即可以返回其仿函数。通过算法for_each()的返回值可以获取仿函数的状态,详见例13-4。
例13-4
例13-4的执行结果为:
在语句for_each(col.begin(),col.end(),MeanV())中,MeanV()产生一个反函数用于记录元素数量,并计算所有元素的总和。此仿函数传递给算法for_each(),后者会针对容器内每个元素调用仿函数。而返回的仿函数被赋值给mv。调用仿函数的成员函数value(),即可获取相应的平均值了。
4.判断式可返回仿函数的状态
所谓判断式,即返回布尔值的一个函数或仿函数。对于STL来说,并不是所有返回布尔值的函数是合法的判断式(谓词)。这样会导致很多意想不到的结果。
例13-5
例13-5的执行结果为:
例13-5中使用了一个仿Nth()函数,当被重复调用时,此仿函数会返回true。若将其传递给算法remove_if()时,此算法会将所有符合条件的元素删除。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。