首页 再呓C++

再呓C++

举报
开通vip

再呓C++ 再呓 C++ “C++是一个足够复杂,但因为其复杂而变得足够有趣的语言” ----------云风 之所以写这篇文章,很大程度上要归咎于一年前曾经许诺过要写一篇关于 STL 方面的学习心得。我想 我还算一个遵守承诺的人,尽管曾经许下的很多承诺都已随风逝去,不过还好,我还有坚持下去的勇气。 经过一年来断断续续的学习,从模板知识到 STL 标准库,再到 STL 源码剖析,还算看了几本大作,七 窍里面也通了六窍,虽说越看越觉得没谱,但也有必要对已学过知识进行一些总结整理,当然这...

再呓C++
再呓 C++ “C++是一个足够复杂,但因为其复杂而变得足够有趣的语言” ----------云风 之所以写这篇文章,很大程度上要归咎于一年前曾经许诺过要写一篇关于 STL 方面的学习 心得 信息技术培训心得 下载关于七一讲话心得体会关于国企改革心得体会关于使用希沃白板的心得体会国培计划培训心得体会 。我想 我还算一个遵守承诺的人,尽管曾经许下的很多承诺都已随风逝去,不过还好,我还有坚持下去的勇气。 经过一年来断断续续的学习,从模板知识到 STL 标准库,再到 STL 源码剖析,还算看了几本大作,七 窍里面也通了六窍,虽说越看越觉得没谱,但也有必要对已学过知识进行一些总结整理,当然这主要是个 人在学习过程中的一个感悟和在模板中较为关键部分的概括,而不是一篇任何意义上的教程,算是温故而 知新吧。“好记性不如烂笔头”,工作后总是很怀念这句话,也许是大学期间听了太多次这句话吧。 最后,当我开始提笔写这篇文章的时候,我期望能够赶在 11 月底前完成,然后等待某个时刻的到来。 虽然如今的他多少让人觉得有点江郎才尽的感觉,虽然最近的一次感动也已经是两年前的《不能说的秘密》, 但周董的新专辑终究是这乏味生活中的一丝期待。此刻应该有很多人抓狂般的将鼠标移到了叉号上吧?手 下留情,我们马上开始这篇关于 C++的不能不说的秘密,人类历史上最伟大的财富(之一):C++ Template & Standard Template Library。 History "Andy, are you crazy?" “Well, yes I am crazy, but why not try it?” 这是 Alexander Stepanov 在收到 Andy Koenig 邮件时的简单对话。时间也回溯到 1994 年 1 月 6 日,当 时的 Koenig 在给 Stepanov 的电子邮件中表示如果 Stepanov 愿意将 STL 的说明文件撰写齐全,在 1 月 25 日 前提出,便可能成为标准 C++的一部份。于是在 Alexander 和 Lee 的拼命赶工中,STL 也开始了自己疯狂的 C++标准化之旅。而在这部 STL 纪传体史书中,我们至少应该记住如下五个人物。 David R. Musser:泛型程序设计观念的奠基人和提倡者。早在 1971 年便开始提倡泛型编程(GP),只 是当时没有任何编程语言支援泛型程序设计,直到 1987 年与 Alex 在 Ada 语言(支持泛型概念)下开发出 一套相关的 Ada library。 Bjarne Stroustrup:被誉为 C++之父。早在 C++原始设计之初,出于对描述参数化容器的愿望,就已经 考虑模板概念的引入。但由于相关设计和实现问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 的不明确,以及害怕会增加 C++本身的复杂度,特别是 担心增加编译和链接时间,这件事情就被推迟。后来在 C++广泛应用的过程中,Bjarne 发现使用 C++最大的 问题就是缺乏一个扩充的标准库,而根本原因就是缺少一种定义容器类的一般机制,于 1989 年在 Cfront 中引入模板机制,这为 STL 在 C++中的实现奠定了基础。此后在 C++ STL 标准化工作中也强力支持,甚至不 惜拖延 C++标准化决议时间,最终促成了 STL 的标准化。【C++语言的设计和演化·第 15 章】 Andy Koenig:在整个 C++ STL 标准化起到穿针引线的作用。当 Andy 听完 Stepanov 对 STL 的介绍以及 看到在惠普实验室的研究成果后异常兴奋,清楚的意识到在 C++标准中引入 STL 的必要性和创新意义。他 将 STL 推广到 C++世界,也给了 Stepanov 一个实现 C++ STL 的平台和支持。 Alexander Stepanov:被誉为 STL 之父。早在 C++诞生的年代,Stepanov 便开始考虑在保证效率的前提 下,将算法从诸多具体应用之中抽象出来的可能性,并同 Musser 等人一起在 Ada 中对 STL 进行实践。在这 期间,Stepanov 意识到,在当时的面向对象程序设计思想中所存在的一些问题,比如抽象数据类型概念所 存在的缺陷。希望通过对软件领域中各组成部分的分类,逐渐形成一种软件设计的概念性框架,在这些驱 动下逐步完善了 STL 中的数据结构和架构框架。随后注意到 C++语言在实现其泛型思想方面所具有的潜在 优势,在 HP 实验室工作期间,和 Meng Lee 的共同努力下,通过模板机制实现了一个包含有大量数据结构 和算法部件的庞大运行库,也就是 STL 的雏形。在标准化的进程中也进行了大量调整,加入了封装内存模式 信息的抽象模块,从而独立于具体平台,甚至连比较成熟的 stream、string 等都以 template 形式重新写过, 最终实现了 STL 的标准化工作。整个标准库到处都是 template! Meng Lee:早期从事 C++编译器工作,对模板机制非常熟悉,很多 STL 的程序都是出自她手。关于她 了解不是很多,但最关键的一点还是要告诉大家,她可是一位亚洲 MM 哦 o(∩_∩)o Component 在这一章中内容比较多,我也意识到仅凭现在自身的水平、仅用三言两语和很短的时间内不可能面面 俱到的描述模板和 STL 这一庞大体系,这里仅根据个人的理解而言。如果真的达到尽善尽美,可能需要一 生来不断的修正和扩充,C++的学习不可能一蹴而就,在学习和使用过程中会有不同的感悟。这里仅仅迈出 第一步。本节分为三个层次分别介绍模板实现机制、语法概念以及 STL 的组件构成。 Template mechanism 模板的实现机制在标准中没有过多规定,也不像面向对象机制中有着比较成熟的解析规则和标准,只 是在最终实现角度定义了语法和规则。很多实现机制都可以由编译器设计者自行提供解决 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 。在 Bjarne 对模板的目标来看,主要是在保证移植性、合理编译和链接效率的前提下实现语法的方便性、运行时效率 和类型安全。坦白说,由于在安全性、易用性、灵活性以及执行文件大小和效率之间的侧重点不同,以及 实现复杂度的巨大,各个编译器之间都会有各自的取舍与平衡点,实现一个十全十美的编译器几乎是一件 不可能的事情。 由于 C++模板机制的首要竞争对手就是宏,所以在灵活性和效率上要求非常严格,因此模板机制几乎 都是在编译和链接时的机制。总体来讲,C++模板本身就是一套复杂的宏语言和虚 函数 excel方差函数excelsd函数已知函数     2 f x m x mx m      2 1 4 2拉格朗日函数pdf函数公式下载 的组合,大部分实现 都放在编译期间处理(类似宏的处理手段),对于动态数据则采用虚函数列表的机制达到运行时的支持。 具体的模板在编译器的解析机制,相关资料也不多,即使连《Inside C++ Model》也只有不多的几页来 描述,主要过程如下【Inside The C++ Object Model】:  在程序编译初期,对于任何 template 相关的信息都不会具现,而是存储在于 object files 中  当 object files 被链接在一起时,会有一个 prelinker 程序执行,用来检测 object files,寻找 template 实体的相互使用和对应的定义  对于使用到的 template 实体而该实体还没有定义的情况,prelinker 会将该文件收集标记,这样 便可以将必要的具现操作指定给特定的文件,同时记录在 prelinker 产生的.ii 文件中  prelinker 重新执行编译器,重新编译每一个.ii 曾被改变过的文件。整个过程不断重复,知道所有 必要的具现操作都完成  链接成可可执行文件 通过对模板实现过程的理解,我们不难看到,在编译器初期看到 template 的时候并没有做任何事,然 后通过对程序的整体解析,对各种必要的具现加以定义,最后通过虚函数表实现必要的动态绑定机制。其 中最为关键和复杂的任务集中在对具现的处理上。简单想,如果把具现出来的类的所有成员函数都定义出 来,肯定能够保证模板的正常使用,但这是以增加文件大小和执行效率作为代价;而如果程序非常巨大, 对于每一个具现(及可能是基本类型也可能是自定义类型)只定义一次,虚函数表的布局合理又是一个极 端复杂的解析过程,自然会增加过多的编译时间和难度。实际上,多个定义可能会产生,而链接器在尽量 优化和避免的前提下也放任这种情况而取其一。很幸运,编译器为我们处理了大多数细节。 Template concept 语法 模板的使用很简单,在 Bjarne 的著作中可以看到为此可谓大煞苦心。一个 template 作为标示(对人也 对编译器),一个<>指定参数(圆括号过度滥用),足矣!然而这种简单中却隐藏着无法预知的不简单。一 方面为了语法简单,编译器为我们做了很多事情,同时也隐藏了很多内幕;另一方面在应用过程中各种复 杂的应用与设计,估计也超出了当初 Bjarne 的想象。在这里主要针对模板、引数推导、实例化三个必不可 少的步骤简单说明,对于(偏)特化、重载、继承等暂不涉及。  模板 C++引入模板的最初目的是设计容器,因此类模板得到最先支持,随后很多算法函数的移植以及 概念上的统一,也引入了函数模板的概念。对于模板参数,C++采用宽松的语法规则,既可以指 类型,也可以指定非类型参数(常数等);既可以是泛型参数,也可以局部特化。类模板支持继 承机制,函数模板也支持重载。此外,由于虚函数的动态绑定机制,不支持虚函数的模板。  参数推导 如上所述,模板支持 C++面向对象的大多数语法。当我们写出一个类模板运行后,感叹“that’s good” 时,我们有没有想过,编译器为此付出了多少?可以说,如果没有名称查询机制,类不会被编 译器了解,如果没有引数推导,参数类型则不得不显示指定。 名称查询,分为(非)受限名称,(非)依赖名称。C++引入命名空间,各种运算符的混杂当编 译器遇到一个名称,需要寻找该名称引用的对象,这并不是一件轻松的事情。在模板中,如果 普通查找没有找到该名称,则对该名称相关的类和命名空间组成集合,在第二次查找中再进行 查找(会忽略 using),为此 C++定义了一些规则来描述“相关”,称之为 ADL,尽可能找到名称所 对应的类型【C++ Template 第九章】 引数推导:在 STL 中占有很重要的地位,针对模板(成员)函数,不适用于模板类。编译器会按 照一套规则就隐式寻找最佳参数类型匹配,这就免去了用户指定类型的繁杂操作。相对普通函 数的推导,模板中采用的是精确匹配【C++ Template 第二、十一章】  实例化 当我们在代码角度实现模板功能,当编译器能够找到正确的名称和参数类型后,我们的编译器 便迎来的最后一步:实例化,将模板解析成真正的 C++代码。 C++实例化即代码具现,主要分为两步,非依赖型在第一步就已经具现,针对依赖性则在第二步 通过 ADL 和引数推导进行具现(POI),生成最后的普通 C++代码。【C++ Template 第十章】 设计 模板作为全新的语言机制,也带来了很多新的设计理念,确实也产生了意想不到的威力。也是目前 C++ 世界最为热门的讨论内容。这里仅列出两个尝尝鲜。 trait 与 policy:在 STL 内存管理特别是优化代码中有比较重要的价值。定义一系列属性,在代码交互 中形成“标准 协议 离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载 ”。其中 trait 注重类型,而 policy 注重行为。从设计的角度讲,这其实非常简单,说是设 计我觉得有点牵强,不过在作用角度,特别对复杂情况和几乎无从处理的问题,这或许是一个简单可行的 好方式。个人觉得 trait 更应该是对类设计人员知识水平和使用习惯的新要求。【C++ Template 第十五章】 metaprogram:利用模板编译期间解析的特点,通过模板递归的方式,可以使用模板在编译期进行计 算,在性能要求较高的程序中会带来不错的好处。不过个人觉得用法限制很大,在大部分性能没有变态要 求的情况下采用此方式多少有点得不偿失。【C++ Template 第十七章】 应用 智能指针:也算是高级应用吧,通过模板绑定(独占、共享),让模板类来负责内存的管理,而在使 用中和原生质真没有区别。成本很低,价值很大。在复杂逻辑情况下,内存很难管理的应用中采用智能指 针应该是一个不错的原则。不过如果能够自己创建一个具备垃圾回收的 new 函数,这种内存池机制在 C++ 中已经没有太多难度,算法、框架以及效率上都比较成熟,我想更有价值【C++ Template 第二十章】 仿函数:„„【C++ Template 第二十二章】 STL component STL 的本质思想是将算法和数据结构之间独立,可以说是对数据结构的完美实践的精品。各种数据结 构的布局、应用;常用算法的支持;主流应用的封装;坦白说相对模板的复杂多变,STL 的知识则非常的少, 可谓是小而精干,背后拥有先进的技术和深厚的理论。下图是 STL 六大组件的相互关系。 STL 框架关系【截取自 STL 源码剖析】 从图中可以看到,在整个 STL 框架中,一切都以容器为中心,为了更有效的数据布局,抽离出 Allocator 模块;为了将行为与数据结构独立,则产生了迭代器的概念;而算法模块匹配迭代器,提供了一种全局函 数,特定的算法往往对应特定的数据结构,因此了解不同的算法针对行的优势和缺陷,对我们解决问题有 着至关重要的价值;为了使用的方便,STL 也为我们提供了一些工具包和各种适配器。 STL Annotated 《STL 源码剖析》,一言以蔽之,STL 的《Inside C++ Object Model》。很难得的一本好书,读完让人有一 种很舒畅的感觉,虽然 SGI 和标准有一定出入,但是在思想上基本一致,建议每一个学习 STL 的人都要居 家常备。相对 Template 在语法设计方面的复杂性,STL 本身在这些层面上并则是小巫见大巫了,不过 STL 在数据管理和产品化结构框架的思想和技巧则非常的有水准,值得大家所了解。在我阅读这本书的时候, 个人觉得最精彩的部分是 Allocator 和 Containers 这几个章节,也对比了 STLPort、MFC、VS2009 中相关部分 的实现,下面很粗略的过一下我觉得最精彩的部分,我也有苦衷,都让侯捷写完了。  Allocator 模块 配置器作用很小,因为多数程序员都适用默认参数;配置器又至关重要,因为大多数操作本质 上都属于内存的操作,这与程序的效率和稳定性息息相关。在配置器中,通过 trait 设计和特化, 多很多常用和可能的性能提升做了很多处理。 一级配置器:STL 中默认的配置器其实在内存处理中比较简单,主要是通过全局函数来方便类型 的创建和释放。在 STL 中对效率的考虑非常极致,比如对常用类型的特化,将内存分配和类型的 构造、析构过程分离,然后通过 trait 机制来尽量避免无意义的构造和析构。 二级配置器:SGI 特有,虽不是标准,也很难说有多大的使用场景,但其中内存池的引入,以及 数据结构的组织和管理,则显得极其优雅。在二级配置器中主要负责小内存(超过 128 字节则 自动采用一级配置器),这往往是程序中最繁琐,最消耗的部分。数据管理主要采用数组+链表 的方式来管理,数组用来管理不同大小的内存块,链表则管理相同大小的内存块,从而形成一 个二维内存管理,其中对使用内存块释放,增加,异常等进行了精致处理和优化,在书中有很 详细的介绍,有兴趣的可以多看一下。 内存管理函数:对内存的使用,STL 提炼出一些常用的全局函数,这在容器的管理中使用率非常 频繁。主要是用于数据构造的不同情况,以及数据本身的特点(POD)进行的优化,同样采用 trait 方式。 在配置器中对内存的控制很精致,对很多使用场景和类型进行了丰富的处理,这也为 STL 在数据 管理以及算法应用打下了坚实的地基!  Containers 模块 很多人对 STL 的第一印象就是容器,或许也是唯一印象。一门语言能有自己的容器,确实是值得 庆祝的事情,而 C++的容器可以说得上是为数据结构量身定做的产品,非常可靠耐用。 每一种数据结构都有自己的优势,自然也继承了先天的劣势,STL 容器的数量比较丰富,简单而 言可以分为两大类,一类是以 vector 和 list 为代表,另一类则以 set 和 map 为代表。 vector:在小数据的情况下具有极佳的效果,由于内存连续,用法非常方便。在空间分布中一般 采用倍数增长的机制。在插入和删除等先天劣势的功能中也做了很多优化工作,比如插入中会 参考插入数据量与剩余空间、可用空间的逻辑关系,尽可能采用批处理的方式来改进效率。 list:vector 和 list 可以说的上是最为常用的容器类型,list 在功能角度可以说和 vector 基本相同, 但在应用场景上和 vector 则有不同的侧重。相对 vector 的内存连续,list 在内存上离散分别,因 此在大数据下具有一定优势,功能上比较灵活,没有太多优化的空间,当然因为数据结构本身 导致迭代器的性能相对 vector 有一定损失,要视具体数据来分析。 rb_tree:平衡二叉树的一种改进,set、map 容器的数据结构。在功能角度将算得上是 vector 和 list 的折中,即避免了 vector 的连续内存的要求,有可以改善 list 在数据查询等方面的差强人意。 在实现角度,rb_tree 则与前者有着巨大的不同(自动排序),也有着先天的劣势(插入),结构 较为复杂,为了在数据插入中排序和平衡会有较为繁琐的调整过程,而这也是二叉树最为核心 的部分。当然,迭代器的实现相对 list 也更复杂一些。  不同 STL 简单对比 在学习过程中,相比 MFC、STLPort 和 VS2009 做了一些研究,赞叹这些神来之笔之外也有一些大 跌眼镜之处,下面结合 vector 列出几点不同: 创建对象:在 MFC 的容器中,所有内存以 char*为基本大小,并没有使用 stl,在构造函数中只 是简单的初始化工作,基本上花费时间很少;而在 STLPort 中,通过初始化列表的优化,但由于 继承导致的“子函数”的因素,在效率上有一些损失;在 VS 中,本身编译器会有很多优化,但 在安全机制上的 if 判断,还有子函数的调用,以及没有采用初始化列表的原因,性能几乎无法 忍受。 内存增长机制:mfc 采用线型的动态增长方式(默认),而 stl 中采用每次增长 50% 方式,在多 数情况下减少申请内存的次数,要优于 mfc。另外,vc9 采用 memcpy 而 STLPort 采用 memmove 总结:通过容器的对比,大可以感觉出三者之间细微处的不同,也增加了我们使用容器的经验。 在 vector 中设置自动增长值非常有必要,而且在不必要情况下不要随便创建空的 vector 对象, 在创建时尽可能设置空间大小,即使大点也可以接受。在其他如插入删除获取等相关函数在处 理思路上和 stl 的都基本一致,MFC 与 STLPort 在这些功能上的效率基本相当。最让人意外的在 VS 中的 STL 加入了过多的安全处理和逻辑判断,代码上写的多少有点“大巧不工”,多少让人有 所失望,在最常用的构造、Add 等函数中效率有不小的下降。对于一款轻巧强大的 STL 来说,犹 如灌铅的羽毛。 Future C++的标准化工作长达 10 年之久,我想这让它失去了一个最为关键的时期,而 STL 库过于精简,并没 有提供类似 Java 那样丰富的库,这让 C++失去了不少使用者。诚然,这些问题的客观因素都可以归结于 C++ 的复杂和易学难用的特点。我也不清楚 C++未来的方向会在哪,无论是丰富的标准库,还是泛型编程与面 向对象的演绎,或者是高效可移植语言的推广,引入成熟的内存管理、回收机制,甚至是 Beyond the C++ Standard Library,C++都有无限的可能。而且随着现代编译器的优化,我完全相信 C++在效率问题上已经不 输于 C。此外,C++是灵活优雅的,在理论体系上相当的完美,当你深入理解后你会被它的优雅所折服。因 此,C++可以说得上是绩优潜力股,丰富的弹性和强大的功能在各个方面都有很多空间,我也永远看好 C++ 的未来。当然,作为技术人员,技术和语言没有好坏之分,往往都有此一时彼一时的起伏,希望所有的人 都能够耐心学习几门语言,大有益处,或许还会影响你分析事物的角度。 由于篇幅限制,在很多地方上做了不少缩水,和当初设想的内容还是有一定出入,不少内容只是写了 一些个人认为最有必要留意的部分,我想今后会在此基础上继续添加新的感悟。当然如果希望对上述内容 有一个详细的理解,确实还是如云风所说,还是去书店看看那一排排的大部头吧,知识永远不可能被如此 压缩的一篇文章所取代。不过写完这篇学习总结,多少有些释然,也算圆了自己的一个承诺,只是没想到 会拖了一年之久,想想一年来的变化和不变化,多少有点感慨。突然觉得自己有些老了,少了一点激情, 多了一丝无奈。不管怎样,如果能看到这里,我都很感谢你,哪怕只能引起你一步的留恋或一秒的回忆, 我也会觉得很满足。 PS:之所以限制篇幅,最重要的原因是本着笔筒以稀为贵的原则,都是限量版哦,呵呵。 参考书籍 C++语言的设计和演化 深入探索 C++模型 C++模板 C++标准程序库 STL 源码剖析 呓语C++ 再呓C++ History Component Template mechanism Template concept STL component STL Annotated Future
本文档为【再呓C++】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_885997
暂无简介~
格式:pdf
大小:598KB
软件:PDF阅读器
页数:6
分类:互联网
上传时间:2012-04-24
浏览量:6