C++ 谓词(predicate) 与 仿函数 ( functor (function object))
谓词与函数对象
谓词 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表达式 函数对象 库定义的函数对象
C++ 谓词(predicate) 与 仿函数 ( functor (function object))的更多相关文章
- 函数对象与仿函数(function object and functor)
part 1. 仿函数在STL组件中的关系 如下图: # 仿函数配合算法完成不同的策略变化. # 适配器套接仿函数. part 2. 仿函数介绍 传递给算法的“函数型实参”不一定得是函数,可以是行为类 ...
- function call操作符(operator()) 仿函数(functor)
主要是需要某种特殊的东西来代表一整组操作 代表一整组操作的当然是函数,过去通过函数指针实现 所以STL算法的特殊版本所接受的所谓条件或策略或一整组操作都以仿函数的形式呈现 #include <i ...
- c++仿函数 functor
内容整理自国外C++教材 先考虑一个简单的例子:假设有一个vector<string>,你的任务是统计长度小于5的string的个数,如果使用count_if函数的话,你的代码可能长成这样 ...
- 仿函数(functor)
仿函数(functor),就是使一个类的使用看上去像一个函数.其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了. In computer programmin ...
- 函数对象(仿函数 functor)
简单地说,函数对象就是一个重载了()运算符的类实例,它可以像一个函数一样使用. #include <iostream> using namespace std; class Add { p ...
- STL仿函数functor
一:仿函数functor介绍 尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数的方法,那就是函数对象. functor,翻译成函数对象,伪函数,算符,是重载了“()”操作符的 ...
- 【STL】-function object
// Generic findMax, with a function object, version #1 // Precondition, a.size() > 0 #include < ...
- 认识js函数对象(Function Object)
认识函数对象(Function Object) 可以用function关键字定义一个函数,对于每个函数可以为其指定一个函数名,通过函 数名来进行调用.这些都是代码给用户的印象,而在JavaScript ...
- C++仿函数(functor)详解
C++仿函数(functor)详解 所谓的仿函数(functor),是通过重载()运算符模拟函数形为的类. 因此,这里需要明确两点: 1 仿函数不是函数,它是个类: 2 仿函数重载了()运算符,使得它 ...
随机推荐
- 使用sphinx为python注释生成docAPI文档
sphinx简介 sphinx是一种基于Python的文档工具,它可以令人轻松的撰写出清晰且优美的文档,由Georg Brandl在BSD许可证下开发. 新版的Python3文档就是由sphinx生成 ...
- 基因型数据正负链怎么翻转(snp flip)
在合并数据过程当中,经常会发现不同来源的数据正负链不是统一的,这是一件很头疼的事. 正负链没有统一的情况下直接合并在一起会产生什么后果呢. 举个最简单的例子,假如我们从小明和小红分别拿到了一批基因型数 ...
- Shenzhen Wanze Technology Co., Ltd.技术支持
本网页为Shenzhen Wanze Technology Co., Ltd.团队的技术支持网址,如果在我们开发的游戏中遇到任何问题,欢迎联系我们! QQ:2535510006 邮箱:25355100 ...
- 移动端播放直播流(video.js 播放 m3u8 流)
流媒体服务器: wowza 流媒体格式: m3u8 播放端:移动端网页(Android.IOS) 播放工具: video.js 代码如下: <!DOCTYPE html> <html ...
- jenkins中启用tag标签
参照里面的第9步: https://www.cnblogs.com/effortsing/p/10468840.html
- 利用Entity Framework修改指定字段中的值
利用Entity Framework修改指定字段中的值一般我们编辑某些模型的时候会用到类似这样的代码: [HttpPost] public ActionResult Edit(Article mode ...
- [LeetCode] 240. Search a 2D Matrix II 搜索一个二维矩阵 II
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the follo ...
- Jacob操作ppt
前几天使用Apache 的POI操作ppt,后来发现转成的图片出现乱码,而且处理了之后,还会有遗留 因此决定换一种处理方式 Jacob 是 JAVA-COM Bridge的缩写,是一个中间件,能够提供 ...
- docker+k8s基础篇三
Docker+K8s基础篇(三) kubernetes上的资源 A:k8s上的常用资源 Pod的配置清单 A:Pod上的清单定义 B:Pod创建资源的方法 C:spec下其它字段的介绍 Pod的生命周 ...
- Qt5 QtQuick系列----QtQuick的Secne Graph剖析(1)
教是言词, 实不是道,道本无言, 言说是妄.------- 达摩 Qt 5提出了一个新的渲染底层,以替代Qt4时期的Graphics View,这个渲染底层就是Scene Graph.Scene Gr ...