事态的发展有时候总会趋向极端,这在那些唯美主义者当中犹是如此。首先声明,我并不是一个唯美主义者,提供第二版程序的改进版,完全是为了让你更深刻的感受到STL的魅力所在。在看完第三版之后,你会强烈感受到这一点。或许你也会变成一个唯美主义者了,至少在STL方面。这应该不是我的错,因为决定权在你手里。下面我们来看看这个绝版的C++程序。

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>using namespace std;void main(void)
{typedef vector<int>              int_vector;typedef istream_iterator<int>              istream_itr;typedef ostream_iterator<int>             ostream_itr;typedef back_insert_iterator< int_vector >    back_ins_itr;// STL中的vector容器int_vector num;// 从标准输入设备读入整数, // 直到输入的是非整型数据为止copy(istream_itr(cin), istream_itr(), back_ins_itr(num));// STL中的排序算法sort(num.begin(), num.end());// 将排序结果输出到标准输出设备copy(num.begin(), num.end(), ostream_itr(cout, "\n"));
}

  在这个程序里几乎每行代码都是和STL有关的(除了main和那对花括号,当然还有注释),并且它包含了STL中几乎所有的各大部件(容器container,迭代器iterator, 算法algorithm, 适配器adaptor),唯一的遗憾是少了函数对象(functor)的身影。

  还记得开头提到的一个典型系统所具有的基本特征吗?--输入+处理+输出。所有这些功能,在上面的程序里,仅仅是通过三行语句来实现的,其中每一行语句对应一种操作。对于数据的操作被高度的抽象化了,而算法和容器之间的组合,就像搭积木一样轻松自如,系统的耦合度被降到了极低点。这就是闪耀着泛型之光的STL的伟大力量。如此简洁,如此巧妙,如此神奇!就像魔术一般,以至于再一次让你摸不着头脑。怎么实现的?为什么在看第二版程序的时候如此清晰的你,又坠入了五里雾中(窃喜)。

  请留意此处的标题(唯美主义的杰作),在实际环境中,你未必要做到这样完美。毕竟美好愿望的破灭,在生活中时常会发生。过于理想化,并不是一件好事,至少我是这么认为的。正如前面提到的,这个程序只是为了展示STL的独特魅力,你不得不为它的出色表现所折服,也许只有深谙STL之道的人才会想出这样的玩意儿来。如果你只是一般性的使用STL,做到第二版这样的程度也就可以了。

  实在是因为这个程序太过"简单",以至于我无法肯定,在你还没有完全掌握STL之前,通过我的讲解,是否能够领会这区区三行代码,我将尽我的最大努力。

  前面提到的迭代器可以对容器内的任意元素进行定位和访问。在STL里,这种特性被加以推广了。一个cin代表了来自输入设备的一段数据流,从概念上讲它对数据流的访问功能类似于一般意义上的迭代器,但是C++中的cin在很多地方操作起来并不像是一个迭代器,原因就在于其接口和迭代器的接口不一致(比如:不能对cin进行++运算,也不能对之进行取值运算--即*运算)。为了解决这个矛盾,就需要引入适配器的概念。istream_iterator便是一个适配器,它将cin进行包装,使之看起来像是一个普通的迭代器,这样我们就可以将之作为实参传给一些算法了(比如这里的copy算法)。因为算法只认得迭代器,而不会接受cin。对于上面程序中的第一个copy函数而言,其第一个参数展开后的形式是:istream_iterator(cin),其第二个参数展开后的形式是:istream_iterator()(如果你对typedef的语法不清楚,可以参考有关的c++语言书籍)。其效果是产生两个迭代器的临时对象,前一个指向整型输入数据流的开始,后一个则指向"pass-the-end value"。这个函数的作用就是将整型输入数据流从头至尾逐一"拷贝"到vector这个准整型数组里,第一个迭代器从开始位置每次累进,最后到达第二个迭代器所指向的位置。或许你要问,如果那个copy函数的行为真如我所说的那样,为什么不写成如下这个样子呢?

copy(istream_iterator<int>(cin), istream_iterator<int>(), num.begin());

你确实可以这么做,但是有一个小小的麻烦。还记得第一版程序里的那个数组越界问题吗?如果你这么写的话,就会遇到类似的麻烦。原因在于copy函数在"拷贝"数据的时候,如果输入的数据个数超过了vector容器的范围时,数据将会拷贝到容器的外面。此时,容器不会自动增长容量,因为这只是简单地拷贝,并不是从末端插入。为了解决这个问题,另一个适配器back_insert_iterator登场了,它的作用就是引导copy算法每次在容器末端插入一个数据。程序中的那个back_ins_itr(num)展开后就是:back_insert_iterator(num),其效果是生成一个这样的迭待器对象。

  终于将讲完了三分之一(真不容易!),好在第二句和前一版程序没有差别,这里就略过了。至于第三句,ostream_itr(cout, "\n")展开后的形式是:ostream_iterator(cout, "\n"),其效果是产生一个处理输出数据流的迭待器对象,其位置指向数据流的起始处,并且以"\n"作为分割符。第二个copy函数将会从头至尾将vector中的内容"拷贝"到输出设备,第一个参数所代表的迭代器将会从开始位置每次累进,最后到达第二个参数所代表的迭代器所指向的位置。

这就是全部的内容。

历史的评价

历史的车轮总是滚滚向前的,工业时代的文明较之史前时代,当然是先进并且发达的。回顾那两个时代的C++程序,你会真切的感受到这种差别。简洁易用,具有工业强度,较好的可移植性,高效率,加之第三个令人目眩的绝版程序所体现出来的高度抽象性,高度灵活性和组件化特性,使你对STL背后所蕴含的泛型化思想都有了些微的感受。

  真幸运,你可以横跨两个时代,有机会目睹这种"文明"的差异。同时,这也应该使你越加坚定信念,使自己顺应时代的潮流。

STL入门第四篇——唯美主义的杰作相关推荐

  1. java邮件接收代码,JavaMail入门第四篇 接收邮件(示例代码)

    上一篇JavaMail入门第三篇 发送邮件中,我们学会了如何用JavaMail API提供的Transport类发送邮件,同样,JavaMail API中也提供了一些专门的类来对邮件的接收进行相关的操 ...

  2. JavaMail入门第四篇 接收邮件

    上一篇JavaMail入门第三篇 发送邮件中,我们学会了如何用JavaMail API提供的Transport类发送邮件,同样,JavaMail API中也提供了一些专门的类来对邮件的接收进行相关的操 ...

  3. 如何高效运作机器学习团队(机器学习入门第四篇)

    本文是机器学习入门教程的第四篇,前三篇分别是: 1.机器学习能为你的业务做什么?有些事情你肯定猜不到 2.关于机器学习算法 你需要了解的东西 3.如何开发机器学习模型? 我们已经讨论了开发机器学习模型 ...

  4. Avalonia跨平台入门第四篇之Popup在uos下问题

    上一篇简单玩耍了Popup,这不正当我洋洋自得的时候前线传来战报:你家伙做的效果在UOS下面有问题;然后直接发来一张捷报: 明明在乌班图和优麒麟都没啥问题,单单就你这个UOS牛,结果发现个神奇的特效: ...

  5. WPF入门第四篇 WPF模板

    WPF模板 1.ControlTemplate 上一篇已经试用过控件模板,我们知道WPF的控件都是继承自Control,在Control类中有一个Template属性,类型就是ControlTempl ...

  6. Android JNI入门第四篇——jni头文件分析

    转载请标明出处: http://blog.csdn.net/michael1112/article/details/56666407 江东橘子的博客 一. 首先写了java文件: public cla ...

  7. java 读取邮件正文_JavaMail入门第五篇 解析邮件

    上一篇JavaMail入门第四篇 接收邮件中,控制台打印出的内容,我们无法阅读,其实,让我们自己来解析一封复杂的邮件是很不容易的,邮件里面格式.规范复杂得很.不过,我们所用的浏览器内置了解析各种数据类 ...

  8. R语言入门第四集 实验三:数据可视化

    R语言入门第四集 实验三:数据可视化 一.资源 [R语言]R语言数据可视化--东北大学大数据班R实训第三次作业 在r中rowsums_R语言初级教程(15): 矩阵(下篇) R语言环境变量的设置 环境 ...

  9. Linux入门第四集!Jar包的入门、使用、部署!怎么打Jar包?

    Linux入门第四集!Jar包的入门.使用.部署!怎么打Jar包? 一.首先要确保JDK8已经安装成功 Linux入门第三集!JDK8的Linux版本资源分享!jdk-8u301-linux-x64. ...

最新文章

  1. 北京智能计算产业研究院落户顺义,中科睿芯联手计算所、顺义区打造“产业园2.0”...
  2. Spring Boot 的 10 个核心模块
  3. e课表项目第二次冲刺周期第七天
  4. SAP FI新手常用代码
  5. 根据HttpServletRequest request 获取当前用户ip地址和ip所属区域
  6. GIS基础知识汇总篇(五)-无人机真正射影像的概念和制作原理
  7. python join函数_Python join()函数
  8. Java工作笔记-Spring Boot + Jdbc + dm7Driver访问数据库(Spring Boot连接达梦数据库)
  9. oracle+st_geometry
  10. vmware下linux的vmware tools安装
  11. 强化学习组队学习task02——马尔可夫决策过程及表格型方法
  12. foreach delete item error
  13. 程序员面试金典——4.1二叉树平衡检查
  14. 【43】学习处理模版化基类内的名称
  15. Android视频裁剪适配,类似于ImageView的scaleType=centerCrop
  16. 北航计算机专硕学硕区别,专硕是什么意思啊?和学硕一样吗?
  17. w8ndows 秒表,关闭 Windows Search,Win8 能变快?
  18. 适合所有手环的app_Redmi Watch体验:手环终结者?
  19. 【deepin】安装与设置win10独立双系统 - 战神Z7-SL7S3安装deepin15.11,并双屏显示
  20. 【windows】网络设置了代理,怎么关闭

热门文章

  1. 字节跳动VP 谢欣:打造10倍速高效组织的秘密!
  2. 3D MAX制作游戏高端人物模型
  3. win7电脑数字键盘失灵怎么办
  4. 高维数据中特征筛选方法的思考总结——多变量分析筛选法
  5. FastStone Capture(好用的截图工具)
  6. 论文排版3-公式编辑
  7. 给定一个整数,请将该数各个位上数字反转得到一个新数。新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零
  8. 运算放大器---功耗(Iq需求)
  9. 几款实用的个人知识管理工具
  10. 什么是GDP平减指数