谓词与函数对象

谓词 predicate

C++ 标准定义谓词如下:

The Predicate parameter is used whenever an algorithm expects a function object that when applied to the result of dereferencing the corresponding iterator returns a value testable as true. In other words, if an algorithm takes Predicate pred as its argument and first as its iterator argument, it should work correctly in the construct if (pred(*first)){...}. The function object pred shall not apply any non-constant function through the dereferenced iterator. This function object may be a pointer to function, or an object of a type with an appropriate function call operator.

换成中文就是:当一个算法需要一函数对象,去应用于解引用(deferencing)迭代器(deferencing 解释: int p;将定义一个指向整数的指针,并p取消引用该指针,这意味着它将实际检索p指向的数据。)的结果,谓词参数返回一个testable值为true。换句话说,换句话说, 如果算法将谓词 pred 作为其参数,first参数是迭代参数,则如果 (pred (* first)) {..} , 它应该在构造中正常工作。函数对象 pred 不应通过解引用迭代器应用于任何非定常(non-constant)函数。此函数对象可以是指向函数的指针, 也可以是具有适当函数调用运算符的类型的对象。

仿函数

functor(函数对象或函数)形式:object + ()
这包括正常函数,函数指针和 () 运算符(函数调用运算符)重载的类对象,即为其定义函数 operator()() 类。
有时我们可以在普通函数不起作用时使用函数对象。STL经常使用函数对象并提供几个非常有用的函数对象。
函数对象是泛型编程的力量和纯抽象概念的另一个例子。我们可以说任何行为都像函数对象是函数。因此,如果我们定义一个行为是函数的对象,它可以用作函数。

#include <iostream> 

struct absValue
{
float operator()(float f){
return f> ?f:-f;
}
}; int main()
{
using namespace std; float f = -123.45; absValue aObj;
float abs_f = aObj(f);
cout <<“f =”<< f <<“abs_f =”<< abs_f << '\n';
return ;
}

正如我们从定义中看到的那样,即使 aObj 是一个对象而不是一个函数,我们也可以对该对象进行调用。效果是运行由对象absValue定义的重载调用操作符。运算符获取浮点值并返回其绝对值。请注意,函数调用运算符必须声明为成员函数。
因此,定义调用操作符的类类型的对象(如absValue对象)称为函数对象。
一个函数的行为是可以通过使用括号和传递参数来调用。

func (arg1 , arg2);

如果我们希望对象以这种方式运行,我们必须通过使用括号和传递参数来调用它们。我们所要做的就是使用适当的参数类型定义operator() :

Class X {
public:
// define "function call" operator
return-value operator() (arguments) const;
...
};

然后我们可以使用这个类的对象来表现我们可以调用的函数:

X fn;
//...
fn(arg1,arg2); //为函数对象fn调用operator()

此调用相当于:

fn.operator()(ARG1,ARG2); //为函数对象fn调用operator()

一个例子:

class Print {
public:
void operator()(int elem)const {
cout << elem <<“”;
}
}; int main(){
vector <int> vect;
for(int i = ; i <; ++ i){
vect.push_back(i);
} Print print_it;
for_each(vect.begin(),vect.end(),print_it);
cout << endl;
return ;
}
for_each(vect.begin(),vect.end(),print_it);

通常,第三个参数可以是仿函数,而不仅仅是常规函数。实际上,这提出了一个问题。我们如何声明第三个参数?我们不能将它声明为函数指针,因为函数指针指定了参数类型。因为容器几乎可以包含任何类型,所以我们事先并不知道应该使用哪种特定类型。STL通过使用模板解决了这个问题。

template<class Iterator, class Function>
Function for_each(Iterator first, Iterator last, Function f) {
while (first != last) {
f(*first);
++first;
}
return f;
}

以下是Nicolai M. Josuttis在“The C ++ Standard Library”中列出的函数对象的一些优点。

  • 功能对象是“智能功能”。
    行为像指针的对象是智能指针。对于行为类似于函数的对象也是如此:它们可以是“智能函​​数”,因为它们可能具有超出operator()的能力。函数对象可以具有其他成员函数和属性。这意味着函数对象具有状态。

  • 每个函数对象都有自己的类型。
    普通函数只有在签名不同时才有不同的类型。但是,当函数对象的签名相同时,它们可以具有不同的类型。实际上,函数对象定义的每个函数行为都有自己的类型。这是使用模板进行泛型编程的重大改进,因为您可以将功能行为作为模板参数传递。

  • 函数对象通常比普通函数更快。
    模板的概念通常允许更好的优化,因为在编译时定义了更多细节。因此,传递函数对象而不是普通函数通常会产生更好的性能。

STL改进了仿函数概念,如下所示:
generator : 是一种可以不带参数调用的函数
一元函数:有一个参数的调用函数
二元函数:有两个参数的调用函数

generator 可以被认为是一种 每次调用都返回 集合/序列的下一个值的函数/对象。

算法的特殊辅助函数是谓词。谓词是返回布尔值的函数(或者可以隐式转换为bool的函数)。换句话说,谓词类是一个仿函数类,其operator() 函数是谓词,即其operator() 返回true或false。
谓词在STL中被广泛使用。标准关联容器的比较函数是谓词,谓词函数通常作为参数传递给find_if等算法。根据其目的,谓词是一元的或二元的。
一元函数返回一个布尔值是一元谓词。
二元函数返回一个布尔值是二元谓词。

谓词的种类算法(algorithm) 的 谓词(predicate) 详解函数 函数指针 lambda表达式 函数对象 库定义的函数对象

转自:https://www.cnblogs.com/gardenofhu/p/10062378.html

C++ 谓词(predicate) 与 仿函数 ( functor (function object))的更多相关文章

  1. 函数对象与仿函数(function object and functor)

    part 1. 仿函数在STL组件中的关系 如下图: # 仿函数配合算法完成不同的策略变化. # 适配器套接仿函数. part 2. 仿函数介绍 传递给算法的“函数型实参”不一定得是函数,可以是行为类 ...

  2. function call操作符(operator()) 仿函数(functor)

    主要是需要某种特殊的东西来代表一整组操作 代表一整组操作的当然是函数,过去通过函数指针实现 所以STL算法的特殊版本所接受的所谓条件或策略或一整组操作都以仿函数的形式呈现 #include <i ...

  3. c++仿函数 functor

    内容整理自国外C++教材 先考虑一个简单的例子:假设有一个vector<string>,你的任务是统计长度小于5的string的个数,如果使用count_if函数的话,你的代码可能长成这样 ...

  4. 仿函数(functor)

    仿函数(functor),就是使一个类的使用看上去像一个函数.其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了. In computer programmin ...

  5. 函数对象(仿函数 functor)

    简单地说,函数对象就是一个重载了()运算符的类实例,它可以像一个函数一样使用. #include <iostream> using namespace std; class Add { p ...

  6. STL仿函数functor

    一:仿函数functor介绍 尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数的方法,那就是函数对象. functor,翻译成函数对象,伪函数,算符,是重载了“()”操作符的 ...

  7. 【STL】-function object

    // Generic findMax, with a function object, version #1 // Precondition, a.size() > 0 #include < ...

  8. 认识js函数对象(Function Object)

    认识函数对象(Function Object) 可以用function关键字定义一个函数,对于每个函数可以为其指定一个函数名,通过函 数名来进行调用.这些都是代码给用户的印象,而在JavaScript ...

  9. C++仿函数(functor)详解

    C++仿函数(functor)详解 所谓的仿函数(functor),是通过重载()运算符模拟函数形为的类. 因此,这里需要明确两点: 1 仿函数不是函数,它是个类: 2 仿函数重载了()运算符,使得它 ...

随机推荐

  1. Qt编写气体安全管理系统28-模拟工具

    一.前言 模拟工具在一些涉及到硬件通信的程序中特别有用,也特别需要,回顾这十年来做过的项目,95%的项目都是软硬件交互的,貌似软硬件结合的项目更有生命力一些,纯软件的或者纯硬件的,并没有那么好控制,如 ...

  2. net ads join 和net rpc join命令的区别

    要将主机加入Active Directory(AD),请输入: #net ads加入-U administrator 输入管理员密码:Passw0rd 使用短域名 - SAMDOM 加入'M1'到dn ...

  3. notepad++删除某关键字所在的行内容

    例如,我要删除zhao这个字符串所在的行 打开notepad++的ctrl+f窗口 点击替换选项,在查找目标输入^.*bp.*$ 其中替换为那里留空,查找模式选择正则表达式,建议也勾选匹配大小写,同时 ...

  4. node端代理浏览器路由 解决浏览器跨域问题

    var _ = require('lodash'); var request = require("request"); /* @LM 2017-02-16 node端代理浏览器路 ...

  5. Java之Java程序的基本结构

    Java的基本结构是 /** * 可以用来自动创建文档的注释 */ public class Hello { public static void main(String[] args) { // 向 ...

  6. Jenkins - 构建流水线

    1 - 以流水线的方式进行构建 关联多任务形成流水线的两种方法 通过定义项目的后续项目,将项目直接关联起来按顺序执行, 另外定义一个用于统筹管理的项目,定义各项目之间的关联性,然后以流水线的方式执行 ...

  7. Spring Boot拦截器实现并和swagger集成后使用拦截器的配置问题

    1. 定义拦截器 LoginInterceptor LoginInterceptor.java是整个登录认证模块中的核心类之一,它实现了HandlerInterceptor类,由它来拦截并过滤到来的每 ...

  8. python-tkinter使用方法——转载(二)

    转载URL:https://www.cnblogs.com/yudanqu/p/9467803.html Tkinter模块("Tk 接口")是Python的标准Tk GUI工具包 ...

  9. STL对map排序

    // sort start typedef struct{ ... }Node; // Map的键是字符串,值是结构体.虽然有自动排序特性,但是按字符串的排序并不能符合要求.此时,Map的key可以视 ...

  10. jwt 0.9.0(三)jwt客户端存储状态可行性分析,及Java代码案例

    Jwt客户端存储状态可行性分析 1.前端首次访问后台,后台生成token,放在http header的Authorization里(官网推荐,可解决跨域cookie跨域问题),并且Authorizat ...