首页 > Coding > 仿函数(function object,函数对象)

仿函数(function object,函数对象)

2016年1月12日 发表评论 阅读评论

引子

前一篇文章讲到了C++11的新特性lambda表达式

lambda表达式的本质是什么呢?为探究这个问题,我们将一段写有lambda表达式的代码反编译,可能会发现一些秘密.

首先写段程序:

在调试该代码时我们打开汇编视图,发现如下代码:

其中 <$_0::operator()(int, int) const>      即对应原代码中的lambda表达式。这里一串重载了"()"(operator())操作符的代码,即本文将要了解的仿函数

Note:  此处的 const  ,也应证了前文 mutable 可变范围 中提到的,lambda的调用运算符为"const-by-value"的

  定义

仿函数(finctor)是一种早期的叫法,在C++11中,标准的叫法为函数对象(function object)。仿函数是一种行为类似函数、具有函数特性的对象。

仿函数是一个对象,而不是函数。仿函数的类通过重载函数操作符"()"(operator())来实现函数调用的特性。

通过下面的例子来简单说明如何使用仿函数

这个例子中,lineA声明了一个对象。这是一个函数对象,其类(结构)定义在functional文件中,是STL内置的模板类。该类用于比较两个参数的大小。

lineB则像函数一样直接给该对象传入两个参数。

lineC是另一种写法。greater<int>() 声明了一个临时对象,然后传入参数(3,4)调用该临时对象。这种写法往往比lineB更加简洁。在STL源码里大量使用了这种写法。

lineD则是使用自定义的函数对象。

Note:lineB中使用了boolalpha,是iostream提供的一个操作符,这将使此后的标准输出中,将bool值输出为"true"或"false",而不是1/0。于其相反的操作为noboolalpha.

STL中的仿函数

仿函数是STL六大组件之一。它一般与STL算法配合使用。

STL内建的仿函数,若以操作数个数据划分,可以分为一元和二元仿函数;若以功能划分,则可分为算术运算(arithmectic)、关系运算(Rational)、逻辑运算(Logical)三大类。

算术类仿函数
  • 加法:plus<T>
  • 减法:minus<T>
  • 乘法:multiplies<T>
  • 除法:divides<T>
  • 模取:modulus<T>
  • 否定:negate<T>
关系运算类仿函数
  • 等于:equal_to<T>
  • 不等于:not_equal_to<T>
  • 大于:greater<T>
  • 大等于:greater_equal<T>
  • 小于:less<T>
  • 小等于:less_equal<T>
逻辑运算类仿函数
  • 逻辑运算And:logical_and<T>
  • 逻辑运算Or:logical_or<T>
  • 逻辑运算Not:logical_not<T>

一般而言,很少有在单纯情况下使用功能极其简单的仿函数的。STL的仿函数主要搭配STL算法。例如对vector<int>元素进行递减排序:

区别与优势

逻辑和算法分离

这使得仿函数可以用于不同的场合,算法也可以和不同逻辑的仿函数搭配使用。参见STL的for_each;

有状态

仿函数是一个对象。它是可以带有状态的。这是指针函数无法实现的。

高性能

仿函数的实现可以是内联的。使得编译器知道算法调用了哪些代码。而指针函数是在运行时才能确定指针指向的函数。

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.