STL — 仿函数的实现原理和应用
2017-04-19 08:33
176 查看
STL仿函数
今天我们来看看一个比较冷门但是很有趣的知识->仿函数,听名字我们就知道,他肯定是让一个不是函数的东西拥有函
数的功能,跟我们之前说的智能指针很类似,那么我们就有理由想到->类,没有错这就是类。这就是面向对象的优点之
处,以前我体会不到面向对象的好处,现在越学越觉得有用。
可不要小看这个仿函数,他可是STL六大组件之一拥有成堆的应用场景以及应用技巧.让我们先来明白一个它最简单的使
用.这个概念,说的通俗点就是在一个类中利用运算符重载重载"()"让类拥有函数的使用特性和功能.仿函数在C语言和
C++中都可以实现,C语言中的仿函数是使用函数指针和回调函数实现的。
我们先来看看一个C语言中的实现:
#include <stdio.h> #include <stdlib.h> //int sort_function( const void *a, const void *b); int sort_function( const void *a, const void *b) { return *(int*)a-*(int*)b; } int main() { int list[5] = { 54, 21, 11, 67, 22 }; qsort((void *)list, 5, sizeof(list[0]), sort_function);//起始地址,个数,元素大小,回调函数 int x; for (x = 0; x < 5; x++) printf("%i\n", list[x]); return 0; }
然后C++就简单多了,具体调用举个例子我们实现一个判断是否相等的仿函数:
template<class T> struct A { bool operator()(const T& a,const T& b) { return (a == b); } }; int main() { A<int>a; cout << a(1, 2) << endl; system("pause"); return 0; }
这就是一个最简单的仿函数了,大家大致应该明白这个仿函数怎么用了吧。现在我对它进行稍微复杂一点的应用,我们
在智能指针中实现过shared_ptr的简单实现,现在我们看看代码:
template<class T> class shared { public: shared(T* ptr) :_ptr(ptr) , _num(new int(1)) { } shared(const shared<T>& ap) :_ptr(ap._ptr) , _num(ap._num) { ++(*_num); } shared<T>& operator=(const shared<T>& ap) { if (_ptr != ap._ptr) { Release(); _ptr = ap._ptr; _num = ap._num; ++(*_num); } return *this; } T* operator->() { return _ptr; } T& operator*() { return *_ptr; } void Release() { if (0 == (--*_num)) { cout << "智能指针爸爸帮你释放空间了" << endl; delete _ptr; delete _num; _ptr = NULL; _num = NULL; } } ~shared() { Release(); } protected: T* _ptr; int* _num; };
但是里面有一个问题就是,我们无论用智能指针指向任何对象它最后都是用delete释放,这个显然是不可以的。因为开
辟空间不仅仅只有new还有new[],malloc。。。。。 所以这个实现有一点简单了,我们现在运用仿函数尝试一下解决
这个问题。
在这里就需要我们思考了,这个怎么办,我们可以这样想要将模板和仿函数联系起来,因为在释放空间的时候数据(到
底是使用delete还是delete[])是从类外传递进来的,那我们可以事先分别实现内部使用delete释放空间和使用
delete[]释放空间的仿函数,然后把它的类从模板里传进来,然后在目标类内创建对象,然后再调用对象的仿函数。
//使用delete释放空间的仿函数 template<class T> class Delete { public: Delete() {} void operator()(T* _ptr) { cout << "delete" << endl; delete _ptr; _ptr = NULL; } ~Delete() {} protected: T* _ptr; }; //使用delete[]释放空间的仿函数 template<class T> class DeleteArray { public: DeleteArray() {} void operator()(T* _ptr) { cout << "delete[]" << endl; delete[] _ptr; _ptr = NULL; } ~DeleteArray() {} };
template<class T,class Del = Delete<T>>
class shared
{};
那么模板就可以设计成这样,让模板的默认属性为delete释放空间,然后把析构函数设计成这样:
inline void Release() { if (0 == (--*_num)) { delete _num; _num = NULL; Del _del; _del(_ptr); } } ~shared() { Release(); }
就是创建一个Del对象,这里我们的Del比如是Delete,那我们的_del(_ptr)的内部,就是用delete释放_ptr,所以我们就
这样把模板和仿函数联系在一起,我画一张图帮我们理解吧;
我们现在慢慢的发现仿函数的用法真的是特别特别的多,也特别的灵活,而我们现在只需要认识他,在它出现的时候知
道这个东西怎么用,平时应用仿函数可能会带给你想象不到的乐趣与便利。
仿函数和模板可以经常在一起搭档,记住,所以他两个你都得学好~
整体代码:
template<class T> class Delete { public: Delete() {} void operator()(T* _ptr) { cout << "delete" << endl; delete _ptr; _ptr = NULL; } ~Delete() {} protected: T* _ptr; }; //使用delete[]释放空间的仿函数 template<class T> class DeleteArray { public: DeleteArray() {} void operator()(T* _ptr) { cout << "delete[]" << endl; delete[] _ptr; _ptr = NULL; } ~DeleteArray() {} }; template<class T, class Del = Delete<T>> class Shared_Ptr { public: Shared_Ptr( T* ptr) :_ptr(ptr) , _nums(new int(1)) {} Shared_Ptr(const Shared_Ptr<T>& cur) :_ptr(cur._ptr) , _nums(cur._nums) { ++(*nums); } Shared_Ptr<T>& operator = (Shared_Ptr<T>& cur) { if (this != &cur) { _ptr = cur._ptr; _nums = cur._nums; ++(*_nums); } return *this; } T& operator*() { return _ptr; } T* operator->() { return _ptr; } ~Shared_Ptr() { Relese(); } void Relese() { if (--(*_nums) == 0) { delete _nums; Del _del; _del(_ptr); _nums = NULL; _ptr = NULL; } } protected: T* _ptr; int* _nums; }; void Test() { Shared_Ptr<int> ptr(new int(1)); Shared_Ptr<string, DeleteArray<string>> ptr2(new string[20]); }
相关文章推荐
- 【STL】栈的实现原理以及应用
- Java虚拟机类装载:原理、实现与应用
- 【转载】Java虚拟机类装载:原理、实现与应用
- Java 虚拟机类装载:原理、实现与应用
- 流式对象的实现原理和应用
- NFramework开源AOP框架ORM的实现原理与应用
- 深入分析基于VCL派生的ActiveX控件的实现原理及应用
- [转载]Java虚拟机类装载--原理、实现与应用
- Java虚拟机类装载:原理、实现与应用[资料]
- Java虚拟机类装载:原理、实现与应用
- Java虚拟机类装载:原理、实现与应用
- Java虚拟机类装载:原理、实现与应用
- Java虚拟机类装载:原理、实现与应用
- Java虚拟机类装载:原理、实现与应用(zt)
- 可网管宽带路由器的实现原理和应用
- Java虚拟机类装载:原理、实现与应用 (摘录)
- Java虚拟机类装载:原理、实现与应用
- NFramework开源AOP框架ORM的实现原理与应用
- Java 虚拟机类装载:原理、实现与应用
- (转)NFramework开源AOP框架ORM的实现原理与应用