1、指针的算术运算
对于一个存储int数据的vector,我们要查找某值是否存在于其中,采用下标操作的做法如下:
int* find(const vector<int> &vec, int value)
{
for(int i = 0; i < vec.size(); i++)
{
if(vec[i] == value)
return &vec[i];
}
return 0;
}

此函数对于存储int型数据的vector实用,但是如果对于其他类型的数据呢?为了达到这个目的,我们使用function template的形式:
template <typename elemType>
elemType* find(const vector<elemType> &vec, const elemType &value)
{
for(int i = 0; i < vec.size(); i++)
{
if(vec[i] == value)
return &vec[i];
}
return 0;
}

现在,新任务出现了,我们需要让这样一个函数能处理vector和array的元素。对于这个问题,我们的解决办法是,传参容器中的元素而不是指明的容器。
对于array,要传入容器中的元素,可以使用array的首尾元素的指针,即:
template <typename elemType>
elemType* find(const elemType *first, const elemType *last, const elemType &value)
{
if(!first || !last)
return 0;
for(;first != last; first++)
{
if(*first == value)
return first;
}
return 0;
}

对于vector,由于其为连续存储结构,同样可以使用此方式,传入容器的首尾元素指针:
vector<string> svec;
find(&svec[0], &svec[svec.size()], search_value);   //当然,首先得保证vector不为空,这里不做多的描述

到此为止,我们可以使用同样的find函数来查找vector和array中的指定元素了,但是此时,又有个新任务,需要find支持list的元素查找。因为list不是连续存储的,所以在find函数体内,就不能使用指针的++运算来获取下一个元素的地址了。

为了解决这个问题,我们在指针的行为之上提供一层抽象化机制,这个机制可以屏蔽掉vector和list的指针操作行为,使用户在find中看不到指针的操作,从而看到vector和list的操作一样,这样就可以将find函数应用于所有的容器类。

2、Iterators(泛型指针)
这层抽象化机制,即iterator类,跟指针的操作类似,主要提供运算有:++,*,==,!=
定义这样一个类,我们需要知道两个信息
(1)迭代对象类型(即容器类型),这可以决定怎么存取下一个元素
(2)迭代器指向的元素类型,决定*(取值,类似指针的*)操作的返回值
例如:
vector<string>::iterator iter;   //iter为vector容器类型的迭代器,指向的元素类型为string类型。
“;;”符号标识迭代器为容器类中的嵌套类型。

那么现在的find函数为:
template <typename IteratorType, typename elemType>
elemType* find(IteratorType first, IteratorType last, const elemType &value)
{
for(;first != last; first++)
{
if(*first == value)
return first;
}
return last;
}

此版本的find函数还不够弹性,原因在于,传入的elemType类型value并不一定支持“==”运算。这个问题的解决办法在于,传入一个函数指针,利用这个函数指针调用的函数来判断,从而取代“==”。这种方法将在后面介绍。

3、泛型算法函数
头文件:#include<algorithm>
搜索算法:find(),count(),adjacent_find(),find_if(),count_if(),binary_search(),find_first_of().
排序算法:merge(),partial_sort(),partition(),random_shuffle(),reverse(),rotate(),sort().
复制删除替换算法:copy(),remove(),remove_if(),replace(),replace_if(),swap(),unique().
关系算法:equal(),includes(),mismatch().
生成与质变算法:fill(),for_each(),generate(),transform().
数值算法:accmulate(),adjacent_difference(),partial_sum(),inner_product().
集合算法:set_union(),set_difference().

4、设计一个泛型算法

需求:找出一组数据中小于10的数
首先想到的算法就是将这组数据中的每个数与10对比,然后满足条件的存储起来。然而,如果需求改变为小于11或者大于10,那么原来的函数就不能用了,所以考虑到这个问题,实现如下算法:
bool less_than(int num1, int num2)
{
return num1 < num2 ? True : False;
}

bool greater_than(int num1, int num2)
{
return num1 > num2 ? True : False;
}

vector<int> filter(const vector<int> &vec, int filter_value, bool (*judge)(int, int))
{
vector<int> vecRe;
vector<int>::iterator itBegin = vec.begin();
vector<int>::iterator itEnd = vec.end();

for(;itBegin != itEnd; itBegin++)
{
if(judge(*itBegin, filter_value))
{
vecRe.push_back(*itBegin);
}
}

return vecRe;
}
当然,还可以使用template实现更加泛型的方法,并且使用function object替代函数指针来提高效率,这里就不讨论了。

STL——泛型编程的更多相关文章

  1. C++ STL泛型编程——在ACM中的运用

    学习过C++的朋友们应该对STL和泛型编程这两个名词不会陌生.两者之间的关系不言而喻,泛型编程的思想促使了STL的诞生,而STL则很好地体现了泛型编程这种思想.这次想简单说一下STL在ACM中的一些应 ...

  2. C++ -- STL泛型编程(一)之vector

    STL提供三种组件:容器,迭代器,算法,它们都支持泛型程序设计标准容器有两类:顺序容器和关联容器. 顺序容器(vector,list,deque,string等)是一系列元素的有序组合. 关联容器(s ...

  3. C++ -- STL泛型编程(二)之set

    set集合容器实现了红黑树的平衡二叉检索树的数据结构,在插入元素时候它会自动调整二叉树的排列,把元素放在适当的位置,以确保每个子树根节点的键值都大于左子树的所有节点的键值,而小于右子树的所有节点的键值 ...

  4. [GeekBand] STL与泛型编程(1)

    在C++语法的学习过程中,我们已经对模板有了基本的了解.泛型编程就是以模板为工具的.泛化的编程思想.本篇文章介绍了一些在之前的文章中没有涉及到的一些模板知识.泛型编程知识和几种容器.关于模板的一些重复 ...

  5. 泛型编程、STL的概念、STL模板思想及其六大组件的关系,以及泛型编程(GP)、STL、面向对象编程(OOP)、C++之间的关系

    2013-08-11 10:46:39 介绍STL模板的书,有两本比较经典: 一本是<Generic Programming and the STL>,中文翻译为<泛型编程与STL& ...

  6. STL之父Stepanov谈泛型编程的发展史

    这是一篇Dr. Dobb's Journal对STL之父stepanov的采访.文中数次提到STL的基本思想.语言的特性.编程的一些根本问题等,非常精彩.这篇文章让我想去拜读下stepanov的大作& ...

  7. [GeekBand] STL与泛型编程(2)

    本篇文章在上一篇文章的基础上进一步介绍一些常用的容器以及STL的一些深入知识. 一. Stack和Queue 栈和队列是非常常用的两种数据结构,由deque适配而来.关于数据结构的知识这里就不在介绍了 ...

  8. [GeekBand] STL与泛型编程(3)

    本篇文章主要介绍泛型算法中的变易.排序.数值算法. 一. 变易算法 所谓变易算法是指那些改变容器中的对象的操作. 1.1 copy组 template <class InputIterator, ...

  9. STL与泛型编程(第一周)

    part 1 C++模版简介 一,模版概观 1.模板 (Templates)是C++的一种特性,允许函数或类(对象)通过泛型(generic types)的形式表现或运行. 模板可以使得函数或类在对应 ...

随机推荐

  1. Python模块 Socket

    一个简单的python socket编程 一.套接字 套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象.它们允许程序接受并 ...

  2. 【java开发系列】—— Tomcat编译报错

    由于之前Eclipse里面有一个可移植性的web工程,但是在我很久没用后,再次登录这个IDE的时候就发现了问题. 首先,我的电脑里面有两个版本的JDK,1.6和1.7.两个版本的Tomcat6和7以及 ...

  3. redis未授权访问getshell

    redis未授权访问的问题一年前就爆了,当时刚开始学安全,还不太懂.今天借着工作的机会来搞一把,看看能不能拿下一台服务器.其实前几天就写好了一直想找个实际环境复现一下,一直没有找到,只说下大致思路. ...

  4. Node.js使用MySQL数据库中对RowDataPacket对象的使用

    使用Node.js开发使用MySQL数据库的网站,在查询后返回一RowDataPacket类型的对象 原先使用toString()方法一直得到仅为object的字符串,无法使用 后思考,才发现忽略了其 ...

  5. 如何打卡后缀为3ds的文件

    打开.3DS文件 3DS文件怎么打开? 用它吧:a3dsviewer,顾名思义,一个3D文件浏览工具,为用户提供一个快速和简单的3DS文件浏览器很容易. 这里是一些主要特点的“a3dsviewer”: ...

  6. EntityFramework Code-First教程(一)

    前言:学习了EF框架这么久,还没有好好总结一番,正好遇到一国外的网站,发现不错,随即翻译过来,一是让自己复习一遍,二是供广大初学者学习,翻译过程中加入了一些自己的理解,如有错误,还请指出,多谢多谢.好 ...

  7. Controller类的方法上的RequestMapping一定要写在Controller类里吗?

    转载请标明出处: https://blog.csdn.net/forezp/article/details/80069961 本文出自方志朋的博客 使用Spring Cloud做项目的同学会使用Fei ...

  8. 菜鸟崛起 DB Chapter 1 数据库概述

    1. 数据库的概述 在目前阶段,如果要存储和管理数据,则离不开数据库.当数据存储到数据库后,就会通过数据库管理系统对这些数据进行组织和管理.数据库由一批数据构成有序的集合,这些数据被存放在结构化的数据 ...

  9. Oracle listener.log 清理

    在oracle中,如果不对监听日志文件进行截断(定期清理),那么监听日志文件会变得越来越大,由于一些老旧的OS不支持2GB以上的文件,故当listener.log文件超过2GB时,会出现无法处理新的连 ...

  10. linux下重新启动oracle

    第一步.以Oracle帐户进入Linux系统 第二步.执行以下命令查看数据库监听器的状况: lsnrctl status 或者查看数据库端口是否被监听(默认1521) netstat -ano | g ...