STL基础--仿函数(函数对象)

1 首先看个仿函数的例子

class X {
   public:
   void operator()(string str) {     // 函数调用运算符,返回类型在operator之前
      cout << "Calling functor X with parameter " << str<< endl;
   }
    operator string () const { return "X"; } //类型转换函数,返回类型在operator之后
};

int main()
{
   X foo;
   foo("Hi");    // 以参数HI调用仿函数X
}
/*
 * 仿函数的好处:
 * 1. 智能函数: 比常规函数有更多的功能,比如可以保存状态(参数化的函数)
 * 2. 有它自己的类型,不用考虑函数重名问题
 * 事实上,类带来的其他好处,封装,继承,多态都可以是仿函数的好处
 */

2 参数化的函数

class X {
   public:
   X(int i) {}
   void operator()(string str) {
      cout << "Calling functor X with parameter " << str<< endl;
   }
};

int main()
{
   X(8)("Hi");
}

// 为什么需要参数化函数,用2个参数的函数代替不行么?

// 只实现+2的功能,如果我想实现加任何数的功能
void add2(int i) {
   cout << i+2 << endl;
}

// 用全局变量,显然不好
// 用模板实现,加任何值的功能,但是val需要编译时常数
template<int val>
void addVal(int i) {
   cout << val+i << endl;
}

// 轮到仿函数登场了
class AddValue {
   int val;
   public:
   AddValue(int j) : val(j) { }
   void operator()(int i) {
      cout << i+val << endl;
   }
};

int main()
{
   vector<int> vec = { 2, 3, 4, 5};
   //for_each(vec.begin(), vec.end(), add2); // {4, 5, 6, 7}
   int x = 2;
   //for_each(vec.begin(), vec.end(), addVal<x>); // {4, 5, 6, 7} ,编译不过
   for_each(vec.begin(), vec.end(), AddValue(x)); // {4, 5, 6, 7}
}

3 内置的仿函数

// 比较 less greater  greater_equal  less_equal  not_equal_to
// 逻辑 logical_and  logical_not  logical_or
// 算术 multiplies minus  plus  divide  modulus  negate

int x = multiplies<int>()(3,4);  //  x = 3 * 4 

if (not_equal_to<int>()(x, 10))   // if (x != 10)
   cout << x << endl;

4 参数绑定

set<int> myset = { 2, 3, 4, 5};
vector<int> vec;

int x = multiplies<int>()(3,4);  //  x = 3 * 4 

// 将元素值乘以10,保存在vec中:
transform(myset.begin(), myset.end(),    // 源
          back_inserter(vec),              // 目的
            bind(multiplies<int>(), placeholders::_1, 10));  // 仿函数
    // multiplies<int>()的第1个参数替换为myset中的元素值
    // vec: {20, 30, 40, 50}

void addVal(int i, int val) {
   cout << i+val << endl;
}
for_each(vec.begin(), vec.end(), bind(addVal, placeholders::_1, 2));

// C++ 03: bind1st, bind2nd

5 将常规函数转为仿函数

double Pow(double x, double y) {
    return pow(x, y);
}

int main()
{
  set<int> myset = {3, 1, 25, 7, 12};
  deque<int> d;
  auto f = function<double (double,double)>(Pow);   //C++ 11
  transform(myset.begin(), myset.end(),     // 源地址
              back_inserter(d),              // 目的
                bind(f, placeholders::_1, 2));  // 仿函数
            //  d: {1, 9, 49, 144, 625}
}
// C++ 03中使用ptr_fun 

6 lambda函数

// 想拷贝5<x<20之间的元素到d
set<int> myset = {3, 1, 25, 7, 12};
deque<int> d;

// 定义一个函数
bool needCopy(int x){
   return (x>20)||(x<5);
}
// 或者用内置仿函数和bind结合
// 两种方法都不方便

transform(myset.begin(), myset.end(),     // source
          back_inserter(d),               // destination
          needCopy
          );

/*
          bind(logical_or<bool>,
              bind(greater<int>(), placeholders::_1, 20),
              bind(less<int>(), placeholders::_1, 5))
*/

// C++ 11 lambda function:
transform(myset.begin(), myset.end(),     // source
          back_inserter(d),              // destination
          [](int x){return (x>20)||(x<5);}    //lambda函数
          );

7 为什么STL中需要仿函数?

set<int> myset = {3, 1, 25, 7, 12}; // myset: {1, 3, 7, 12, 25}
// 同:
set<int, less<int> > myset = {3, 1, 25, 7, 12};

bool lsb_less(int x, int y) {
      return (x%10)<(y%10);
}

class Lsb_less {
   public:
   bool operator()(int x, int y) {
      return (x%10)<(y%10);
   }
};
int main()
{
  set<int, Lsb_less> myset = {3, 1, 25, 7, 12};  // myset: {1,12,3,25,7}
  ...
}

8 谓词

 /*
 * 一种特殊的仿函数:
 * 1. 返回一个boolean值
 * 2. 不改变数据
 */

class NeedCopy {
   bool operator()(int x){
      return (x>20)||(x<5);
   }
};

transform(myset.begin(), myset.end(),     // source
          back_inserter(d),               // destination
          NeedCopy()
          );

// 谓词用于比较或者条件判断

原文地址:https://www.cnblogs.com/logchen/p/10200546.html

时间: 2024-08-01 12:56:00

STL基础--仿函数(函数对象)的相关文章

STL 算法中函数对象和谓词

STL 算法中函数对象和谓词 函数对象和谓词定义 函数对象: 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.一个类对象,表现出一个函数的特征,就是通过"对象名+(参数列表)"的方式使用一个类对象,如果没有上下文,完全可以把它看作一个函数对待.          这是通过重载类的operator()来实现的.          "在标准库中,函数对象被广泛地使用以获得弹性",标准库中的很多算法都可以使用函数

3.2 STL中的函数对象类模板

*: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. 2)less是STL中最常用的函数对象类模板,其定义如下: template<class _Tp> struct less { bool oprator()(const _Tp&_x,const _Tp&_y)const { return _c<_y; } } 要判断两个i

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

函数对象: 重载函数调用操作符的类.其对象常称为函数对象(function object),即它们是行为类似函数的对象. 一个类对象,表现出一个函数的特征,就是通过"对象名+(參数列表)"的方式使用一个类对象,假设没有上下文,全然能够把它看作一个函数对待. 这是通过重载类的operator()来实现的. "在标准库中.函数对象被广泛地使用以获得弹性".标准库中的非常多算法都能够使用函数对象或者函数来作为自定的回调行为: demo #include <iostr

浅析STL 谓词 + 仿函数 + 函数指针(c)

一:起因 (0)提到C++ STL,首先被人想到的是它的三大组件:Containers(容器), Iterators(迭代器), Algorithms(算法).容器为用户提供了常用的数据结构(如,vector,list,deque,stack,map,multimap,set,multiset,外加string),算法大多是独立于容器的常用的基本算法(一般在algorithm头文件中,其中sort比较常用),迭代器是由容器提供的一种接口,算法通过迭代器来操控容器.详情请看 博客 (1)接下来要介

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

函数对象: 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.一个类对象,表现出一个函数的特征,就是通过"对象名+(参数列表)"的方式使用一个类对象,如果没有上下文,完全可以把它看作一个函数对待. 这是通过重载类的operator()来实现的. "在标准库中,函数对象被广泛地使用以获得弹性",标准库中的很多算法都可以使用函数对象或者函数来作为自定的回调行为: demo #include <iostrea

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

先来感受一下C++中的函数对象和函数指针: template<typename T> void printer(int a, int b, T func){ cout<<func(a, b)<<endl; } 在STL中定义了很多像上面这样的模板,这里的T是一个可调用(实现了括号运算符)的东西. 这使得我们在使用模板时可以指定一个计算策略,它可以是函数对象,也可以是函数指针. Less<int>便是一个常见的函数对象,常用来配置容器或算法.<funct

C++STL 预定义函数对象和函数适配器

预定义函数对象和函数适配器 预定义函数对象基本概念:标准模板库STL提前定义了很多预定义函数对象,#include <functional> 必须包含. 1使用预定义函数对象: void main() { plus<int> intAdd; int x = 10; int y = 20; int z = intAdd(x, y); //等价于 x + y cout << z << endl; plus<string> stringAdd; str

python基础之====函数对象、函数嵌套、名称空间与作用域、装饰器

阅读目录 一 函数对象 二 函数嵌套 三 名称空间与作用域 四 闭包函数 五 装饰器 六 练习题 一 函数对象 一 函数是第一类对象,即函数可以当作数据传递 #1 可以被引用 #2 可以当作参数传递 #3 返回值可以是函数 #3 可以当作容器类型的元素 二 利用该特性,优雅的取代多分支的if def foo(): print('foo') def bar(): print('bar') dic={ 'foo':foo, 'bar':bar, } while True: choice=input(

[基础] AHK函数对象初窥 ① _实例2_实际可用版

;# 母文章 https://zhuanlan.zhihu.com/p/48977298;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 脚本名称:函数对象初窥①_实例2 [直接可用版本] ; 脚本版本号 v0.2 ; AHK版本: 1.1.30 ; 语言:中文 ; 作者:心如止水<QQ:2531574300> <Autohotkey高手群(34