zoukankan      html  css  js  c++  java
  • ###STL学习--函数对象

    点击查看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
  • 相关阅读:
    log4net 配置
    Sublime Text 2 安装Package Control和插件的两种方法
    Silverlight中ListBox的数据绑定
    在Silverlight 5 项目中创建单元测试项目
    const V.S readonly
    鼠标和键盘操作的全局钩子库
    数码管图片
    正则表达式
    ToString的格式化字符串
    C# Builder
  • 原文地址:https://www.cnblogs.com/gr-nick/p/3973137.html
Copyright © 2011-2022 走看看