C++的标准模板库(STL)是革命性的,但是要想学会用好STL却并不容易。在本书中,畅销书作家Scott Meyers(Effective C++和More Effective C++的作者)揭示了专家总结的一些关键规则,包括专家们总是采用的做法,以及专家们总是避免的做法。通过这些规则,STL程序员可以最大限度地使用STL。\r\n 其他的书只是描述了STL中有些什么内容,而本书则讲述了如何使用STL。本书共有50条指导原则,在讲述每一条指导原则的时候,Scott Meyers都提供了透彻的分析和深刻的实例,所以读者不仅可以学到要做什么,而且还能够知道什么时候该这样做,以及为什么要这样做。\r\n 本书的亮点包括以下几个方面:\r\n ?关于选择容器的建议,其中涉及到的容器有:标准STL容器(例如vector和list)、非标准的STL容器(例如hash_set和hash_map),以及非STL容器(例如bitset)。\r\n ?一些改进效率的技术,通过它们可以最大程度地提高STL(以及使用STL的程序)的效率。\r\n ?一些深层次的知识,其中涉及到迭代器、函数对象和分配子(allocator)的行为,也包括程序员总是应该避免的做法。\r\n ?对于那些同名的算法和成员函数,如find,根据它们行为方式上的微妙差异,本书给出了一些指导原则,以保证它们能被正确地使用。\r\n ?本书也讨论了潜在的移植性问题,包括如何避免这些移植性问题的各种简单途径。\r\n 如同Meyers的其他著作一样,本书充满了从实践中总结出来的智慧。它清晰、简明、透彻的风格必将使每一位STL程序员受益匪浅。\r\n\r\n 作者简介:Scott Meyers:世界顶级的C++软件开发技术权威之一。他是两本畅销书Effective C++和More Effective C++的作者,以前曾经是C++R的专栏作家。他经常为C/C Users Journal和Dr.Dobb''s Journal撰稿,也为全球范围内的客户做咨询活动。他也是Advisory Boards for NumeriX LLC和InfoCruiser公司的成员。他拥有Brown University的计算机科学博士学位。
引言 \r\n第1章 容器\r\n 第1条:慎重选择容器类型。\r\n 第2条:不要试图编写独立于容器类型的代码。 \r\n 第3条:确保容器中的对象拷贝正确而高效。 \r\n 第4条:调用empty而不是检查size()是否为0。 \r\n 第5条:区间成员函数优先于与之对应的单元素成员函数。 \r\n 第6条:当心C++编译器最烦人的分析机制。 \r\n 第7条:如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉。 \r\n 第8条:切勿创建包含auto_ptr的容器对象。 \r\n 第9条:慎重选择删除元素的方法。 \r\n 第10条:了解分配子(allocator)的约定和限制。 \r\n 第11条:理解自定义分配子的合理用法。 \r\n 第12条:切勿对STL容器的线程安全性有不切实际的依赖。 \r\n第2章 vector和strin\r\n 第13条:vector 和string优先于动态分配的数组。 \r\n 第14条:使用reserve来避免不必要的重新分配。 \r\n 第15条:注意string 实现的多样性。 \r\n 第16条:了解如何把vector和string数据传给旧的API。 \r\n 第17条:使用“swap技巧”除去多余的容量。 \r\n 第18条:避免使用vector。 \r\n第3章 关联容器 \r\n 第19条:理解相等(equality)和等价(equivalence)的区别。 \r\n 第20条:为包含指针的关联容器指定比较类型。 \r\n 第21条:总是让比较函数在等值情况下返回false。 \r\n 第22条:切勿直接修改set或multiset中的键。 \r\n 第23条:考虑用排序的vector替代关联容器。 \r\n 第24条:当效率至关重要时,请在map::operator[]与map::insert之间谨慎做出选择。 \r\n 第25条:熟悉非标准的哈希容器。 \r\n第4章 迭代器 \r\n 第26条:iterator优先于const_iterator、reverse_iterator以及const_reverse_iterator。\r\n 第27条:使用distance和advance将容器的const_iterator转换成iterator。 \r\n 第28条:正确理解由reverse_iterator的base()成员函数所产生的iterator的用法。 \r\n 第29条:对于逐个字符的输入请考虑使用istreambuf_iterator。 \r\n第5章 算法 \r\n 第30条:确保目标区间足够大。 \r\n 第31条:了解各种与排序有关的选择。 \r\n 第32条:如果确实需要删除元素,则需要在remove这一类算法之后调用erase。 \r\n 第33条:对包含指针的容器使用remove这一类算法时要特别小心。 \r\n 第34条:了解哪些算法要求使用排序的区间作为参数。 \r\n 第35条:通过mismatch或lexicographical_compare实现简单的忽略大小写的字符串比较。 \r\n ……\r\n第6章 函数子、函数子类、函数及其他 \r\n第7章 在程序中使用STL \r\n参考书目\r\n附录A:地域性与忽略大小写的字符串比较 \r\n附录B:对Microsoft的STL平台的说明
就像本书的前两本姊妹作(Effective C++、More Effective C++)一样,本书的侧重点仍然在于提升读者的经验,只不过这次将焦点瞄准了C++标准库,而且是其中最有意思的一部分——STL。
C++是一门易学难用的编程语言,从学会使用C++到用好C++需要经过不断的实践。Scott Meyers的这三本姊妹作分别从各个不同的角度来帮助你缩短这个过程。C++语言经过了近二十年的发展,正在渐趋完善。尽管如此,在使用C++语言的时候,仍然有许多陷阱,有的陷阱非常显然,一经点拨就可以明白;而有的陷阱则不那么直截了当,需要仔细地分析才能揭开那层神秘的面纱。
本书是针对STL的经验总结,书中列出了50个条款,绝大多数条款都解释了在使用STL时应该注意的某一个方面的问题,并且详尽地分析了问题的来源、解决方案的优劣。这是作者在教学和实践过程中总结出来的经验,其中的内容值得我们学习和思考。
STL的源码规模并不大,但是它蕴含的思想非常深刻。在C++标准化的过程中,STL也被定格和统一。对于每一个STL实现,我们所看到的被分为两部分:一是STL的接口,这是应用程序赖以打交道的基础,也是我们所熟知的STL;二是STL的实现,特别是一些内部的机理,有的机理是C++标准所规定的,但是有的却是实现者自主选择的。在软件设计领域中有一条普遍适用的规则是“接口与实现分离”,但是对于STL,你不能简单地使用这条规则。虽然你写出来的程序代码只跟STL的接口打交道,但是用好STL则需要建立在充分了解STL实现的基础之上。你不仅需要了解对所有STL实现都通用的知识,也要了解针对你所使用的STL实现的特殊知识。那么,应该如何来把握接口与实现之间的关系呢?本书讲述了许多既涉及接口也关系到具体实现的STL用法,通过对这些用法的讲解,读者可以更加清楚地了解应该如何来看待这些与实现相关的知识。
这两年来,有关STL的书籍越来越多,而且许多C++书籍也开始更加关注于STL这一部分内容。对于读者来说,这无疑是一件好事,因为STL难学的问题终于解决了。我们可以看到,像vector和string等常用的STL组件几乎出现在任何一个C++程序中。但是,随之而来的STL难用的问题却暴露出来了,程序员要想真正发挥STL的强大优势并不容易。在现有的STL书籍中,像本书这样指导读者用好STL的书籍并不多见。
本书沿袭了作者一贯的写作风格,以条款的形式将各种使用STL的经验组织在一起,书中主要包括以下内容:
如何选择容器的类型。STL中容器的类型并不多,但是不同的容器有不同的特点,所以选择恰当的容器类型往往是解决问题的起点。本书中还特别介绍了与vector和string两种容器有关的一些注意事项。
涉及到关联容器有更多的陷阱,一不留神就可能陷入其中。作者专门指出了关联容器中一些并不直观的要点,还介绍了一种非标准的关联容器——哈希容器。
迭代器是STL中指针的泛化形式,也是程序员访问容器的重要途径。本书讨论了与const_iterator和reverse_iterator有关的一些问题。以我个人之见,本书这部分内容略显单薄,毕竟迭代器在STL中是一个非常关键的组件。
STL算法是体现STL功能的地方,一个简单的算法调用或许完成了一件极为复杂的事情,但是要用好STL中众多的算法并不容易,本书给出了一些重要的启示。
函数对象是STL中用到的关键武器之一,它使得STL中每一个算法都具有极强的扩展性,本书也特别讨论了涉及到函数和函数对象的一些要点。
其他的方方面面,包括在算法和同名成员函数之间如何进行区别、如何考虑程序的效率、如何保持程序的可读性、如何解读调试信息、关于移植性问题的考虑,等等。
本书并没有面面俱到地介绍所有要注意的事项,而只是挑选了一些有代表性的,也是最有普遍适用性的问题和例子作为讲解的内容。有些问题并没有完美的解决方案,但是,作者已经把这个问题为你分析透了,所以最终的解决途径还要取决于作为实践者的你。
本书的翻译工作是我和陈铭、邹开红合作完成的,其中邹开红完成了前25条的初译工作,陈铭完成了后25条的初译工作,最后我完成了所有内容的终稿工作,同时我也按照原作者给出的勘误作了修订。错误之处在所难免,请读者谅解。
对于每一个期望将STL用得更好的人,这本书值得一读。
潘爱民
2003年6月16日
北京大学燕北园
It came without ribbons! It came without tags!
It came without packages, boxes or bags!
—— Dr. Seuss, How the Grinch Stole
Christmas!, Random House, 1957
我第一次写关于STL(Standard Template Library,标准模板库)的介绍是在1995年,当时我在More Effective C++的最后一个条款中对STL做了粗略的介绍。此后不久,我就陆续收到一些电子邮件,询问我什么时候开始写Effective STL。
有好几年时间我一直在拒绝这种念头。刚开始的时候,我对STL并不非常熟悉,根本不足以提供任何关于STL的建议。但是随着时间的推移,以及我的经验的增长,我的想法开始有了变化。毫无疑问,STL库代表了程序效率和扩展性设计方面的一个突破,但是当我开始真正使用STL的时候,却发现了许多我原来不可能注意到的实际问题。除了最简单的STL程序以外,要想移植一个稍微复杂一点的STL程序都会面临各种各样的问题,这不仅仅是因为STL库实现有各自的特殊之处,而且也是因为底层的编译器对于模板的支持各不相同——有的支持非常好,但有的却非常差。要获得STL的正确指南并不容易,所以,学习“STL的编程方式”非常困难,即使在克服了这个阶段的障碍之后,你要想找到一份既容易理解又精确描述的参考文档仍然是一大困难。可能最沮丧的是,即使一个小小的STL用法错误,也常常会导致一大堆的编译器诊断信息,而且每一条诊断信息都可能有上千个字符长,并且大多数会引用到一些在源代码中根本没有提到的类、函数或者模板(几乎都很难理解)。尽管我对STL赞赏有加,并且对STL背后的人们更是钦佩无比,但是要向从事实际开发工作的程序员推荐STL却感到非常不舒服。因为,我自己并不确定要有效地使用STL是否是可能的。
然后,我开始注意到了一些让我非常惊讶的事情。尽管STL存在可移植性问题,尽管它的文档并不完整,尽管编译器的诊断信息有如传输线上的噪音一样,但是,我的许多咨询客户正在使用STL。而且,他们并不只是把STL拿来玩一玩,而是在用它开发实际的产品。这是一个很重要的启示。过去我知道STL是一个设计非常考究的模板库,这时我逐渐感觉到,既然程序员们愿意忍受移植性的麻烦、不够完整的文档以及难以理解的错误消息,那么这个库除了良好的设计以外,一定还有其他更多的优势。随着专业程序员的数量越来越多,我意识到,即使是一个很差的STL实现,也胜过没有实现。
更进一步,我知道STL的境况正在好转。C++库和编译器越来越多地遵从C++标准,好的文档也开始出现了(请参考本书后面所附的参考资料目录),而且编译器的诊断信息也在改进(不过我们还需要等待它们改进得更好,在此期间,你可以参考第49条给出的一些针对如何处理诊断信息的建议)。因此我决定投身到这场STL运动中,尽我的一份绵薄之力。本书就是我努力的结果:50条有效使用STL的经验。
我原来的计划是在1999年的下半年写作本书,脑子里一直是这样想的,并且也有了一个提纲。但后来我改变了路线。我搁下了本书的写作,而去开发一门有关STL的引导性培训课程,并且也教授了几组程序员。大约一年以后,我又回到这本书的写作上,并根据培训课程中积累的经验重新修订了本书的提纲。就如同Effective C++成功地以实际程序员所面临的问题为基础一样,我希望本书也以类似的方式来面对STL编程过程中的各种实际问题,特别是那些对于专业开发人员尤为重要的实际问题。
我总是在寻求各种途径来提高自己对于C++的理解。如果你有新的关于STL编程学习方法的建议,或者你对于本书中给出的指导原则有任何看法的话,请一定告诉我。而且,我一直追求的目标是,力求使本书尽可能地准确到位,所以,本书中的每一个错误,只要报告给了我,无论是技术上的、语法上的,还是印刷上的错误,或者其他原因的错误,我都会很高兴地在将来的印刷中向第一位报告错误的人表示感谢。请把你的指导建议、你的看法,以及你的批评意见发送到estl@aristeia.com。
我为本书维护了一份自第一次印刷以来的修订纪录,其中包括错误的改正情况、一些说明以及技术更新。你可以在本书的勘误页面上找到这份纪录:http://www.aristeia.com/ BookErrata/estl1e-errata.html。
如果你希望在我对本书做出修改时接到通知的话,我建议你加入到我的邮件列表中。我通过该邮件列表来向那些对我的C++工作有兴趣的人发布通告。详细情况请参考http:// www.aristeia.com/MailingList/。
Scott Douglas Meyers
http://www.aristeia.com/
STAFFORD, OREGON
2001.4
无封面