仿函数解读

合集下载

仿函数的作用

仿函数的作用

仿函数的作用
仿函数是一种强大的编程技术,它最大的优势在于可以将复杂的编程任务变得简单易懂。

首先要明白仿函数的含义,它指的是可以像函数一样使用的表达式,用来代替基础特征的其他函数。

仿函数作为编程技术的一部分,最大的特点在于它可以极大地简化程序设计。

这就意味着,使用仿函数,程序设计者可以以更加高效、连贯的方式完成其程序设计任务,而不必写数十行的复杂程序代码。

仿函数也有其他优势,其中一个便是可以极大地提高程序设计效率。

此外,仿函数还可以使程序设计者简化其程序设计中的棘手问题,而且它还可以将面向对象的程序设计上的逻辑干净地组织起来。

另外,仿函数还能够提高程序设计复杂度,从而使程序设计者避免出现满足关键功能需求而带来额外复杂性的情况。

此外,仿函数还可以使程序设计者有效利用它们已有的程序设计技术,从而提高程序设计的可重用性。

总的来说,仿函数是一种功能强大的编程技术,它能够显著简化程序设计人员的工作,使他们可以以更高效的方式完成其程序设计任务。

因此,众多程序设计师都将仿函数纳入自己的程序设计技术体系中,以发挥它独有的作用。

浅析C++仿函数

浅析C++仿函数

浅析C++仿函数1.为什么要有仿函数我们先从⼀个⾮常简单的问题⼊⼿。

假设我们现在有⼀个数组,数组中存有任意数量的数字,我们希望能够计数出这个数组中⼤于10的数字的数量,你的代码很可能是这样的:#include <iostream>using namespace std;int RecallFunc(int *start, int *end, bool (*pf)(int)){int count=0;for(int *i=start;i!=end+1;i++){count = pf(*i) ? count+1 : count;}return count;}bool IsGreaterThanTen(int num){return num>10 ? true : false;}int main(){int a[5] = {10,100,11,5,19};int result = RecallFunc(a,a+4,IsGreaterThanTen);cout<<result<<endl;return 0;}RecallFunc()函数的第三个参数是⼀个函数指针,⽤于外部调⽤,⽽IsGreaterThanTen()函数通常也是外部已经定义好的,它只接受⼀个参数的函数。

如果此时希望将判定的阈值也作为⼀个变量传⼊,变为如下函数就不可⾏了:bool IsGreaterThanThreshold(int num, int threshold){return num>threshold ? true : false;}虽然这个函数看起来⽐前⾯⼀个版本更具有⼀般性,但是它不能满⾜已经定义好的函数指针参数的要求,因为函数指针参数的类型是bool (*)(int),与函数bool IsGreaterThanThreshold(int num, int threshold)的类型不相符。

仿函数——精选推荐

仿函数——精选推荐

仿函数仿函数的通俗定义:仿函数(functor)⼜称为函数对象(function object)是⼀个能⾏使函数功能的类。

仿函数的语法⼏乎和我们普通的函数调⽤⼀样,不过作为仿函数的类,都必须重载operator()运算符,class Func{public:void operator() (const string& str) const{cout<<str<<endl;}};1 Func myFunc;2 myFunc("helloworld!");>>>helloworld!函数(functor)⼜称之为函数对象(function object),其实就是重载了operator()操作符的struct或class,没有什么特别的地⽅。

仿函数(functor)使⼀个类的使⽤看上去象⼀个函数,这个类就有了类似函数的⾏为,就是⼀个仿函数类了。

如下⾯的代码定义了⼀个⼆元的仿函数(有两个参数):struct IntLess{bool operator()(int _left, int _right) const{return _left<_right;}};为什么要使⽤仿函数呢?1)仿函数⽐⼀般的函数灵活。

2)仿函数有类型识别,可以作为模板参数。

3)执⾏速度上仿函数⽐函数和指针要更快的。

怎么使⽤仿函数?除了在stl⾥,别的地⽅你很少会看到仿函数的⾝影。

⽽在stl⾥仿函数最常⽤的就是作为函数的参数,或者模板的参数。

在stl⾥有⾃⼰预定义的仿函数,⽐如所有的运算符,=,-,*,/,⽐如⽐较符号<、>、<=、>=等。

stl中的'<'仿函数是less:// TEMPLATE STRUCT lesstemplate<class _Ty>struct less : public binary_function<_Ty, _Ty, bool>{ // functor for operator<bool operator()(const _Ty& _Left, const _Ty& _Right) const{ // apply operator< to operandsreturn (_Left < _Right);}};从上⾯的定义可以看出,less就是⼀个含有模板的结构图,并在结构体内重载了operator()运算符。

仿函数传入thread

仿函数传入thread

仿函数传入thread仿函数传入 thread1 简介仿函数是一种特殊的函数类,它可以接受任意的参数,并且提供一般函数的调用接口,可以用来实现一些特殊的功能。

本文讲解了如何使用仿函数和 thread 来实现多线程编程的技术。

2 关于 thread 的介绍thread 是 C++11 引入的一个多线程库,可以用来实现多线程编程。

它使用这种形式的创建线程:thread t1(func1);其中,func1 是一个函数,它将作为一个线程来运行, t1 是一个 thread 对象,它用来控制线程的运行状态。

3 仿函数传入 thread在 thread 构造函数中,可以使用仿函数来代替一般函数。

使用这种形式:thread t1(std::function<void(int)>(func1), arg);这里,func1 是一个函数,它有一个 int 类型的参数,arg 是一个 int 类型的值,用来传递给 func1 函数。

4 示例下面这个例子演示了如何使用仿函数和 thread 来构造一个多线程应用程序:#include <iostream>#include <thread>#include <functional>void func1(int n){std::cout << 'func1 called: ' << n << std::endl;}int main(int argc, char* argv[]){int n = 10;//构造 thread 对象std::thread t1(std::function<void(int)>(func1), n);t1.join();return 0;}这段代码将创建一个单线程,线程中调用 func1 函数,并传入 n 参数,func1 函数的参数是 10。

仿函数 使用

仿函数 使用

仿函数使用
仿函数是C++中的一种特殊函数对象,它可以像普通函数一样调用,也可以像一般对象一样使用。

仿函数可以重载函数调用操作符
'()',使得它能够像函数一样被调用,同时还可以接受参数和返回值。

在实际应用中,仿函数经常用于STL算法和容器中,作为函数参数来操作元素。

例如,在排序算法中,可以使用仿函数来指定排序规则;在容器中,可以使用仿函数来指定查找和删除的条件。

使用仿函数需要注意以下几点:
1. 仿函数必须定义函数调用操作符'()',并且可以重载。

2. 仿函数可以有自己的成员变量和函数。

3. 仿函数可以是普通函数或类成员函数,也可以是Lambda表达式。

4. 仿函数可以作为函数参数或返回值,也可以在容器中存储。

总之,仿函数是一种强大的工具,可以让我们更方便地操作数据,实现更加灵活的算法和数据结构。

因此,学习和掌握仿函数的使用是C++程序员必备的技能之一。

- 1 -。

c++STL之函数对象(仿函数)

c++STL之函数对象(仿函数)

c++STL之函数对象(仿函数)概念:重载函数调⽤操作符的类,其对象被称为函数对象;函数对象使⽤重载的()时,⾏为类似函数调⽤,也叫仿函数;本质:函数对象是⼀个类,不是⼀个函数;函数对象使⽤:- 函数对象在使⽤时,可以像普通函数那样调⽤, 可以有参数,可以有返回值- 函数对象超出普通函数的概念,函数对象可以有⾃⼰的状态- 函数对象可以作为参数传递#include<iostream>using namespace std;#include <string>class MyAdd{public:int operator()(int v1,int v2){return v1 + v2;}};// 1、函数对象在使⽤时,可以像普通函数那样调⽤, 可以有参数,可以有返回值void test01(){MyAdd myAdd;cout << myAdd(10, 10) <<endl;}//2、函数对象超出普通函数的概念,函数对象可以有⾃⼰的状态class MyPrint{public:MyPrint(){this->count = 0;}void operator()(string test) const{cout << test << endl;this->count++;}int count; // 内部⾃⼰状态};void test02(){MyPrint myPrint;myPrint("hello world");myPrint("hello world");myPrint("hello world");myPrint("hello world");cout << "myPrint调⽤次数为: " << myPrint.count << endl;}//3、函数对象可以作为参数传递void doPrint(MyPrint & mp, string test){mp(test);}void test03(){MyPrint myPrint;doPrint(myPrint, "Hello c++");}int main() {//test01();//test02();test03();system("pause"); return0;}。

仿射函数和仿射集

仿射函数和仿射集

仿射函数和仿射集是数学中的两个重要概念,它们在许多领域都有广泛的应用。

仿射函数是一种在数学和工程中常用的变换函数,而仿射集则是一种在图像处理中常用的数据结构。

下面将对这两个概念进行详细介绍。

一、仿射函数仿射函数是一种在数学和工程中常见的函数类型,它是在射影几何中的仿射变换下保持不变的函数。

具体来说,仿射函数是同时满足平移、旋转、反射等变换条件的函数。

它可以表示为输入和输出之间的映射关系,即y = f(x)。

仿射函数的性质包括:1. 平移不变性:当输入x在一定范围内变化时,输出y会根据函数f的形状进行相应变化,但不会因为x的变化而改变。

2. 线性性质:仿射函数通常具有线性性质,即在一定的范围内可以视为一次函数的变换。

3. 变换关系:仿射函数可以根据输入和输出的数据关系进行具体实现,如比例、对称等。

在实际应用中,仿射函数被广泛应用于各种领域,如信号处理、图像处理、计算机视觉等。

通过仿射函数可以对输入数据进行变换,以便更好地分析和处理数据。

二、仿射集仿射集是一种在图像处理中常用的数据结构,它是一种集合运算方式,用于表示图像中的不同区域和像素之间的关系。

具体来说,仿射集是通过对图像中的像素进行分类和分组,形成一种可操作的集合。

仿射集的性质包括:1. 唯一性:仿射集中的每个元素只能对应于图像中的一个像素。

2. 连通性:仿射集中的元素具有一定的连通性,可以描述图像中的不同区域和像素之间的关系。

3. 可扩展性:可以通过增加或删除像素来扩展或修改仿射集。

在实际应用中,仿射集被广泛应用于图像处理和计算机视觉领域,如边缘检测、图像分割、特征提取等。

通过使用仿射集,可以对图像中的不同区域和像素进行分类和分组,以便更好地分析和处理图像数据。

综上所述,仿射函数和仿射集是数学和工程中两个重要的概念,它们在许多领域都有广泛的应用。

仿射函数是一种变换函数,具有平移不变性、线性性质和变换关系等性质;而仿射集是一种集合运算方式,用于表示图像中的不同区域和像素之间的关系,具有唯一性、连通性和可扩展性等性质。

inverse multiquadrics(拟多二次)函数

inverse multiquadrics(拟多二次)函数

inverse multiquadrics(拟多二次)函数拟多二次函数,也被称为反函数多二次函数,是一种常用的核函数。

它在机器学习和数据挖掘等领域广泛应用于非线性模型的构建和解决非线性问题。

拟多二次函数的定义如下:f(r) = sqrt((ε*r)^2+1),其中ε是一个常数,通常取较小的正数。

拟多二次函数与多二次函数(Multiquadrics function)非常相似,只是通过取开平方根的方式对函数进行了变换。

拟多二次函数是多二次函数的反函数,因此它的值域也是非负实数。

拟多二次函数在插值、回归、函数逼近和预测等领域有广泛的应用。

它具有以下几个特点:1. 全局性:拟多二次函数对所有点的插值误差都是全局最小的,因此适用于大范围的插值问题。

2. 平滑性:拟多二次函数在整个定义域上是连续可导的,具有很好的平滑性质。

这使得它对于数据点的微小扰动具有较强的稳定性。

3. 收敛性:随着数据点数量的增加,拟多二次函数逼近真实函数的能力会不断增强。

因此,当数据量较大时,使用拟多二次函数可以得到更精确的模型。

拟多二次函数在实际应用中的一种常见形式是径向基函数(Radial Basis Function, RBF)。

它的表达形式为:f(x) = Σ(wi * sqrt((ε*||xi-x||)^2+1)),其中xi是输入变量,x是待预测的变量,wi是权重,ε是控制函数平滑程度的参数。

在机器学习领域,拟多二次函数常用于支持向量机(Support Vector Machines, SVM)、径向基函数神经网络(Radial Basis Function Neural Network, RBFNN)等模型中。

它们通过拟多二次函数来表示模型的非线性部分,从而提高模型的拟合能力。

此外,拟多二次函数还可以用于数据的聚类分析、降维等任务。

通过将数据点映射到高维空间,并使用拟多二次函数来度量它们之间的距离或相似性,可以更有效地进行数据的分类和聚类。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

仿函数,仿函数类,函数等等条款38:把仿函数类设计为用于值传递C和C++都不允许你真的把函数作为参数传递给其他函数。

取而代之的是,你必须传指针给函数。

比如,这里有一个标准库函数qsort的声明:void qsort(void *base, size_t nmemb, size_t size,int (*cmpfcn)(const void*, const void*));条款46解释了为什么sort算法一般来说是比qsort函数更好的选择,但在这里那不是问题。

问题是qsort声明的参数cmpfcn。

一旦你忽略了所有的星号,就可以清楚地看出作为cmpfcn传递的参数,一个指向函数的指针,是从调用端拷贝(也就是,值传递)给qsort。

这是C和C++标准库都遵循的一般准则,也就是,函数指针是值传递。

STL函数对象在函数指针之后成型,所以STL中的习惯是当传给函数和从函数返回时函数对象也是值传递的(也就是拷贝)。

最好的证据是标准的for_each声明,这个算法通过值传递获取和返回函数对象:template<class InputIterator,class Function>Function // 注意值返回for_each(InputIterator first,InputIterator last,Function f); // 注意值传递实际上,值传递的情况并不是完全打不破的,因为for_each的调用者在调用点可以显式指定参数类型。

比如,下面的代码可以使for_each通过引用传递和返回它的仿函数:class DoSomething:public unary_function<int, void> { // 条款40解释了这个基类void operator()(int x) {...}...};typedef deque<int>::iterator DequeIntIter; // 方便的typedefdeque<int> di;...DoSomething d; // 建立一个函数对象...for_each<DequeIntIter, // 调用for_each,参数DoSomething&>(di.begin(), // 类型是DequeIntIterdi.end(), // 和DoSomething&;d); // 这迫使d按引用// 传递和返回但是STL的用户不能做这样的事,如果函数对象是引用传递,有些STL算法的实现甚至不能编译。

在本条款的剩余部分,我会继续假设函数对象总是值传递。

实际上,这事实上总是真的。

因为函数对象以值传递和返回,你的任务就是确保当那么传递(也就是拷贝)时你的函数对象行为良好。

这暗示了两个东西。

第一,你的函数对象应该很小。

否则它们的拷贝会很昂贵。

第二,你的函数对象必须单态(也就是,非多态)——它们不能用虚函数。

那是因为派生类对象以值传递代入基类类型的参数会造成切割问题:在拷贝时,它们的派生部分被删除。

(切割问题怎么影响你使用STL的另一个例子参见条款3。

)当然效率很重要,避免切割问题也是,但不是所有的仿函数都是小的、单态的。

函数对象比真的函数优越的的原因之一是仿函数可以包含你需要的所有状态。

有些函数对象自然会很重,保持传这样的仿函数给STL算法和传它们的函数版本一样容易是很重要的。

禁止多态仿函数是不切实际的。

C++支持继承层次和动态绑定,这些特性在设计仿函数类和其他东西的时候一样有用。

仿函数类如果缺少继承就像C++缺少“++”。

的确有办法让大的和/或多态的函数对象仍然允许它们把以值传递仿函数的方式遍布STL。

这就是了。

带着你要放进你的仿函数类的数据和/或多态,把它们移到另一个类中。

然后给你的仿函数一个指向这个新类的指针。

比如,如果你想要建立一个包含很多数据的多态仿函数类。

template<typename T>class BPFC: // BPFC = “Big Polymorphicpublic // Functor Class”unary_function<T, void> { // 条款40解释了这个基类private:Widget w; // 这个类有很多数据,Int x; // 所以用值传递... // 会影响效率public:virtual void operator()(const T& val) const; // 这是一个虚函数,... // 所以切割时会出问题};建立一个包含一个指向实现类的指针的小而单态的类,然后把所有数据和虚函数放到实现类:template<typename T> // 用于修改的BPFCclass BPFCImpl{ // 的新实现类private:Widget w; // 以前在BPFC里的所有数据int x; // 现在在这里...virtual ~BPFCImpl(); // 多态类需要// 虚析构函数virtual void operator()(const T& val) const;friend class BPFC<T>; // 让BPFC可以访问这些数据};template<typename T>class BPFC: // 小的,单态版的BPFCpublic unary_function<T, void> {private:BPFCImpl<T> *pImpl; // 这是BPFC唯一的数据public:void operator()(const T& val) const // 现在非虚;{ // 调用BPFCImpl的pImpl->operator() (val);}...};BPFC::operator()的实现例证了BPFC所有的虚函数是怎么实现的:它们调用了在BPFCImpl中它们真的虚函数。

结果是仿函数类(BPFC)是小而单态的,但可以访问大量状态而且行为多态。

我在这里忽略了很多细节,因为我勾勒出的基本技术在C++圈子中已经广为人知了。

《Effective C++》的条款34中有。

在Gamma等的《设计模式》[6]中,这叫做“Bridge模式”。

Sutter在他的《Exceptional C++》[8]中叫它“Pimpl惯用法”.从STL的视角看来,要记住的最重要的东西是使用这种技术的仿函数类必须支持合理方式的拷贝。

如果你是上面BPFC的作者,你就必须保证它的拷贝构造函数对指向的BPFCImpl对象做了合理的事情。

也许最简单的合理的东西是引用计数,使用类似Boost的shared_ptr,你可以在条款50中了解它.实际上,对于本条款的目的,唯一你必须担心的是BPFC的拷贝构造函数的行为,因为当在STL中被传递或从一个函数返回时,函数对象总是被拷贝——值传递,记得吗?那意味着两件事。

让它们小,而且让它们单态。

条款39:用纯函数做判断式我讨厌为你做这些,但我们必须从一个简短的词汇课开始:判断式(predicate)是返回bool(或者其他可以隐式转化为bool的东西)。

判断式在STL中广泛使用。

标准关联容器的比较函数是判断式,判断式函数常常作为参数传递给算法,比如find_if和多种排序算法。

(排序算法的概览可以在条款31找到。

)∙纯函数是返回值只依赖于参数的函数。

如果f是一个纯函数,x和y是对象,f(x, y)的返回值仅当x 或y的值改变的时候才会改变。

在C++中,由纯函数引用的所有数据不是作为参数传进的就是在函数生存期内是常量。

(一般,这样的常量应该声明为const。

)如果一个纯函数引用的数据在不同次调用中可能改变,在不同的时候用同样的参数调用这个函数可能导致不同的结果,那就与纯函数的定义相反。

现在已经很清楚用纯函数作判断式是什么意思了。

我要做的所有事情就是使你相信我的建议是有根据的。

要帮我完成这件事,我希望你能原谅我再增加一个术语所给你带来的负担。

∙一个判断式类是一个仿函数类,它的operator()函数是一个判断式,也就是,它的operator()返回true 或false。

正如你可以预料到的,任何STL想要一个判断式的地方,它都会接受一个真的判断式或一个判断式类对象。

就这些了,我保证!现在我们已经准备好学习为什么这个条款提供了有遵循价值的指引。

条款38解释了函数对象是传值,所以你应该设计可以拷贝的函数对象。

用于判断式的函数对象,有另一个理由设计当它们拷贝时行为良好。

算法可能拷贝仿函数,在使用前暂时保存它们,而且有些算法实现利用了这个自由。

这个论点的一个重要结果是判断式函数必须是纯函数。

想知道这是为什么,先让我们假设你想要违反这个约束。

考虑下面(坏的实现)的判断式类。

不管传递的是什么参数,它严格地只返回一次true:第三次被调用的时候。

其他时候它返回假。

class BadPredicate: // 关于这个基类的更多信息public unary_function<Widget, bool> { // 请参见条款40public:BadPredicate(): timesCalled(0) {} // 把timesCalled初始化为0bool operator()(const Widget&){return ++timesCalled == 3;}private:size_t timesCalled;};假设我们用这个类来从一个vector<Widget>中除去第三个Widget:vector<Widget> vw; // 建立vector,然后// 放一些Widgets进去vw.erase(remove_if(vw.begin(), // 去掉第三个Widget;vw.end(), // 关于erase和remove_if的关系BadPredicate()), // 请参见条款32vw.end());这段代码看起来很合理,但对于很多STL实现,它不仅会从vw中除去第三个元素,它也会除去第六个!要知道这是怎么发生的,就该看看remove_if一般是怎么实现的。

记住remove_if不是一定要这么实现:template <typename FwdIterator, typename Predicate>FwdIterator remove_if(FwdIterator begin, FwdIterator end, Predicate p){begin = find_if(begin, end, p);if (begin == end) return begin;else {FwdIterator next = begin;return remove_copy_if(++next, end. begin, p);}}这段代码的细节不重要,但注意判断式p先传给find_if,后传给remove_copy_if。

相关文档
最新文档