点击查看Evernote原文

#@author:       gr
#@date: 2014-08-13
#@email: forgerui@gmail.com

在stl中,函数对象被大量地使用,用以提高代码的通用性及效率。stl也提供了一些常用的函数对象类型。

###stl学习

 |--迭代器

 |--类属算法

 |--容器

   |--vector

   |--deque

   |--list

   |--set

   |--map

 |--函数对象

 |--适配器

 |--分配器

一、Contents

1. 所谓函数对象

函数对象是行为类似函数的对象。一个类对象,表现出一个函数的特征,即通过对象名+(参数列表)的方式使用一个类对象。

2. 初见函数对象

int sum = add(a, b)可以看做是调用add函数或者使用函数对象,如下:

//1. 完全可以看做是调用add函数
int sum = add(a, b);
//2. 当然也可以看作是使用函数对象,可以通过如下的定义:
Template <class T>
class Add{
public:
T operator() (T a, T b){
return a + b;
}
};
Sum<int> add;s
int sum = add(a, b);

3. 为何要使用函数对象

那么为什么不使用更简单的函数,而选择看起来更复杂的函数对象呢?

在一些情况下,为了使程序富于变化,增加程序的通用性,有时需要将函数当作参数传递,这就需要使用函数指针。

stl类属算法中有一个accumulate函数,其中需要传递一个函数。如下:

//accumulate函数实现,最后一个参数是函数指针
template<typename InputIterator, typename T>
T accumulate(InputIterator first, InputIterator last, T init, T (*binary_function)(T a, T b)){
while(first != last){
init = binary_function(init, *first++);
}
return init;
}
//声明的函数
int product(int a, int b){ return a*b;}
int main(){
int arr[] = {1, 3, 5, 2, 1};
vector<int> vec(arr, arr+6);
//传递声明的函数指针
int product = accumulate(vec.begin(), vec.end(), 1, &product);
}

这样的实现有个问题是通用性不强。函数指针原型可以写为

T (*binary_function) (T a, T b);

这样的函数可以和int product(int, int)匹配,但如果T类型很大,为了提高效率,需要将上面的语句写为如下:

T (*binary_function) (const T& a, const T& b);

则product将**无法与之匹配××,此时必须将函数重写为

int product(const int&, const int&);

另外一个问题在于效率,必须通过指针才能调用这个函数,所以无法使用内联的方式,如果要执行的函数很小,进行一次函数调用将会有相对大的额外开销,而如果这个函数调用是在一个循环中,可以想象出其对效率有严重的影响。

4. 使用函数对象解决问题

现在修改accumulate函数,使用函数对象作为参数。

template <typename InputIterator, typename T, typename FunObj>
T accumulate(InputIterator first, InputIterator last, T init, FunObj obj){
while(first != last){
init = obj(init, *first++);
}
return init;
}

使用这种定义的优点是,可以传递各式各样的类对象,并且可以对operator()进行重载,以匹配多种类型的函数调用,而函数指针则只能接受指定类型的函数,这无疑提高了通用性

另外,编译器可以对operator()进行内联,从而取消调用函数的开销。

More,使用类对象可以提供额外信息,类对象可以有数据成员,可以记录一些状态,这样可以本地封装信息,而无需采用静态或全局数据来实现...

5. stl中提供的函数对象类

  • 算术运算类

    plus, minus, multiplies, divides, modules, negate
  • 比较运算

    equal_to, not_equal_to, greater, less, greater_equal, less_equal
  • 逻辑运算

    logical_and, logical_or, logical_not

二、Miscellany

@author gr
@mail forgerui@gmail.com

###STL学习--函数对象的更多相关文章

  1. C++ STL 之 函数对象适配器

    谓词是指普通函数或重载的 operator()返回值是 bool 类型的函数对象(仿函数).如果operator 接受一个参数,那么叫做一元谓词,如果接受两个参数,那么叫做二元谓词,谓词可作为一个判断 ...

  2. C++ STL 之 函数对象

    重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象,也叫仿函数(functor),其实就是重载“()”操作符,使得类对象可以像函数那样调用.注意 ...

  3. 条款20 STL函数对象

    继承标准STL的函数对象 1: struct PopLess : public atd::binary_function<state,state,bool> 2: { 3: bool op ...

  4. STL学习笔记8 -- 函数对象

    重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.一个类对象,表现出一个函数的特征,就是通过“对象名+(参数列表)”的方式使用一个类对象,如果 ...

  5. STL学习笔记(六) 函数对象

    条款38:遵循按值传递的原则来设计仿函数 仿函数都是 pass-by-value Function for_each(InputIterator first, InputIterator last, ...

  6. 3.2 STL中的函数对象类模板

    *: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. ...

  7. 【实习记】2014-08-15文档太少看着源码用cgicc+stl库之模板谓词函数对象

        总结1: 今天找到了昨天scanf的问题答案,scanf与printf一样的神奇而复杂,稍不留神,就会被坑.scanf函数在读入非空白符分割的多个字符串的解决方法是这个:/* 以 | 分割 * ...

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

    预定义函数对象基本概念:标准模板库STL提前定义了很多预定义函数对象 1)使用预定义函数对象: #include <iostream> #include <cstdio> #i ...

  9. STL算法设计理念 - 函数对象和函数对象当参数和返回值

    函数对象: 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.一个类对象,表现出一个函数的特征,就是通过"对象名+(参数列表)&qu ...

随机推荐

  1. [置顶] 【cocos2d-x入门之五】导演类CCDirector

    原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/12646337 既然cocos2d-x都帮我们封装好了,使得开发与平台无关,那 ...

  2. C++学习笔记(十二):类继承、虚函数、纯虚函数、抽象类和嵌套类

    类继承 在C++类继承中,一个派生类可以从一个基类派生,也可以从多个基类派生. 从一个基类派生的继承称为单继承:从多个基类派生的继承称为多继承. //单继承的定义 class B:public A { ...

  3. MATLAB学习拾遗

    1.坐标轴修饰 axis equal:axis([0,6,0,6]) 不修饰则为默认网格 grid on 2.不太漂亮的pretty命令 3. Laplace变换 syms t s a b f1=ex ...

  4. maven快速入门

    一.maven maven可以说是管理项目的优秀工具,管理jar包 二.mave安装 1.先安装jdk(本文不详细讲) 2.安装maven ①.maven下载   http://maven.apach ...

  5. ThinkPHP3.2.3新特性之:数据库设置

    ThinkPHP3.2.3版本数据库驱动采用PDO完全重写,配置和使用上面也比之前版本更加灵活和强大,我们来了解下如何使用. 首先,3.2.3的数据库配置信息有所调整,完整的数据库设置包括: /* 数 ...

  6. IE下载打印文件的时候,下载打印闪一下就没有了

    这是因为我们的浏览器没有将文件下载的自动提示设为启用.点击IE菜单栏中的“工具”—“Internet选项”-安全—可信站点—自定义级别 1,添加信任站点 打开IE浏览器,输入需要下载文件的地址 选择[ ...

  7. C#/Access-数据库获取自动编号的最大值

    //conStrSQL你改成你的access,我这里用的SQL2005string conStrSQL = "Data Source=xx.xx.xx.xx;Initial Catalog= ...

  8. 什么是IDOC,以及IDOC的步骤

    创建IDOC:   第一步:WE31 创建IDOC所包含的字段.   第二步:WE30 创建IDOC 把Segment分配给IDOC   第三步:WE81  创建信息类型   第四步:WE82   把 ...

  9. 一个方便的shell命令,查看软件安装目录

    查看软件安装路径:whereis phpfind / -name nginx.configfind 查找 / 从根目录 -name 文件查找

  10. 写给新入IT的新人们

    IT=挨踢,这是IT人的自嘲,进入IT行业是有四五年了,也算得上是一个"老人"了吧,见了不少新人,面试了不少新人,也带了一些新人,多多少少还是有点发言权的. 关于书本 新人们经常会 ...