《Effective C++》笔记 01 - 让自己习惯 C++

C++ 语言是一门有着众多特性的语言,要发挥其真正的、全部威力,还是要去掌握这些特性,并且是深入理解。这里第一章 4 个条款,是 C++ 语言的,也是这里全部 55 条条款的最基础性的东西,是应当首先掌握的。

条款 01 - 视 C++ 为一个语言联邦

  • C++ 高效编程守则视状况而变化,取决于你使用 C++ 的哪一部分。
  • 组成 C++ 的 4 个主要次语言(sublanguage)
    • C
    • Object-Oriented C++
    • Template C++
    • STL

补充知乎上姚冬大佬关于 C++ 四大特性的讲解:

为了兼容C语言,不得不继承下来的特性,比如#include,强制类型转换,直接内存操作,基础类型和函数系统,宏。

为了零开销实现OOP而设计的特性,比如 class继承和派生,虚函数,函数重载。

为了开发效率而设计的特性,比如template以及一些列stl,算符重载,auto。

为了解决实际问题不得不向现实妥协而设计的特性,比如 explicit,mutable,xxxxx_cast,register,volatile,inline,asm,template特化,friend。

第一种特性在真正需要和C语言打交道是要小心使用,第二种特性才是主要使用的,第三种特性只在遇到开发效率问题时使用,第四种特性要尽量避免使用,尽量不要制造需要这些特性才能解决的问题。

https://www.zhihu.com/question/444555079/answer/1754123101

条款 02 - 尽量以 const、enum、inline 替换 #define

  • 对于单纯常量,最好以 const 对象或 enums 替换 #defines 。
  • 对于形似函数的宏(macros),最好改用 inline 函数替换 #defines 。

条款 03 - 尽可能使用 const

  • 将某些东西声明为 const 可帮助编译器侦测出错误用法。const 可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体。
  • 编译器强制实施 bitwise constness,但你编写程序时应该使用“概念上的常量性”(conceptual constness)。
  • 当 const 和 non-const 成员函数有着实质等价的实现时,令 non-const 版本调用 const 版本可避免代码重复。

条款 04 - 确定对象被使用前已先被初始化

  • 为内置型对象进行手工初始化,因为 C++ 不保证初始化它们。
  • 构造函数最好使用成员初始列(member initialization list),而不要在构造函数本体内使用赋值操作(assignment)。初始列列出的成员变量,其排列次序应该和它们在 class 中的声明次序相同。
  • 为免除“跨编译器单元之初始化次序”问题,请以 local static 对象替换 non-local static 对象。

廖杰良 - 2018-11-9

已标记关键词 清除标记
相关推荐
基本信息 原书名:Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition) 原出版社: Addison-Wesley Professional 作者:(美)Scott Meyers 译者:侯捷 丛书名: 传世经典书丛 出版社:电子工业出版社 ISBN:9787121123320 出版日期:2011 年1月 开本:16开 页码:336 版次:3-1 编辑本段 编辑推荐 传承大师智慧 领悟技术本真 经典名著 翻译良品 典藏不二之选 编辑本段 内容简介 有人说c++程序员可以分为两类,读过effective c++的和没读过的。世界顶级c++大师scott meyers成名之作的第三版的确当得起这样的评价。当您读过这本书之后,就获得了迅速提升自己c++功力的一个契机。 在国际上,本书所引起的反响,波及整个计算机技术的出版领域,余音至今未绝。几乎在所有c++书籍的推荐名单上,本书都会位于前三名。作者高超的技术把握力、独特的视角、诙谐轻松的写作风格、独具匠心的内容组织,都受到极大的推崇和仿效。这种奇特的现象,只能解释为人们对这本书衷心的赞美和推崇。 这本书不是读完一遍就可以束之高阁的快餐读物,也不是用以解决手边问题的参考手册,而是需要您去反复阅读体会的,c++是真正程序员的语言,背后有着精深的思想与无以伦比的表达能力,这使得它具有类似宗教般的魅力。希望这本书能够帮您跨越c++的重重险阻,领略高处才有的壮美风光,做一个成功而快乐的c++程序员。 编辑本段 作译者 Scott Meyers是全世界最知名的C++软件开发专家之一。他是畅销书《Effective C++》系列(Effective C++,More Effective C++Effective STL)的作者,又是创新产品《Effective C++ CD》的设计者和作者,也是Addison-Wesley的“Effective Software Development Series”顾问编辑,以及《Software Development》杂志咨询板成员。他也为若干新公司的技术咨询板提供服务。Meyers于1993年自Brown大学获得计算机博士学位。侯捷是计算机技术书籍的作家、译者、书评人 编辑本段 目录 译序 vii 中英简繁术语对照 ix 目录 xvii 序言 xxi 致谢 xxiii 导读 1 1 让自己习惯c++ 11 accustoming yourself to c++ 11 条款01:视c++ 为一个语言联邦 11 view c++ as a federation of languages 11 条款02:尽量以const, enum, inline替换 #define 13 prefer consts,enums, and inlines to #defines 13 条款03:尽可能使用const 17 use const whenever possible 17 条款04:确定对象被使用前已先被初始化 26 make sure that objects are initialized before they're used 26 2 构造/析构/赋值运算 34 constructors, destructors, and assignment operators 34 条款05:了解c++ 默默编写并调用哪些函数 34 know what functions c++ silently writes and calls 34 条款06:若不想使用编译器自动生成的函数,就该明确拒绝 37 explicitly disallow the use of compiler-generated functions you do not want 37 条款07:为多态基类声明virtual析构函数 40 declare destructors virtual in polymorphic base classes 40 条款08:别让异常逃离析构函数 44 prevent exceptions from leaving destructors 44 条款09:绝不在构造和析构过程中调用virtual函数 48 never call virtual functions during construction or destruction 48 条款10:令operator= 返回一个reference to *this 52 have assignment operators return a reference to *this 52 条款11:在operator= 中处理“自我赋值” 53 handle assignment to self in operator= 53 条款12:复制对象时勿忘其每一个成分 57 copy all parts of an object 57 3 资源管理 61 resource management 61 条款13:以对象管理资源 61 use objects to manage resources 61 条款14:在资源管理类中小心copying行为 66 think carefully about copying behavior in resource-managing classes 66 条款15:在资源管理类中提供对原始资源的访问 69 provide access to raw resources in resource-managing classes 69 条款16:成对使用new和delete时要采取相同形式 73 use the same form in corresponding uses of new and delete 73 条款17:以独立语句将newed对象置入智能指针 75 store newed objects in smart pointers in standalone statements 75 4 设计与声明 78 designs and declarations 78 条款18:让接口容易被正确使用,不易被误用 78 make interfaces easy to use correctly and hard to use incorrectly 78 条款19:设计class犹如设计type 84 treat class design as type design 84 条款20:宁以pass-by-reference-to-const替换pass-by-value 86 prefer pass-by-reference-to-const to pass-by-value 86 条款21:必须返回对象时,别妄想返回其reference 90 don't try to return a reference when you must return an object 90 条款22:将成员变量声明为private 94 declare data members private 94 条款23:宁以non-member、non-friend替换member函数 98 prefer non-member non-friend functions to member functions 98 条款24:若所有参数皆需类型转换,请为此采用non-member函数 102 declare non-member functions when type conversions should apply to all parameters 102 条款25:考虑写出一个不抛异常的swap函数 106 consider support for a non-throwing swap 106 5 实现 113 implementations 113 条款26:尽可能延后变量定义式的出现时间 113 postpone variable definitions as long as possible 113 条款27:尽量少做转型动作 116 minimize casting 116 条款28:避免返回handles指向对象内部成分 123 avoid returning "handles" to object internals 123 条款29:为“异常安全”而努力是值得的 127 strive for exception-safe code 127 条款30:透彻了解inlining的里里外外 134 understand the ins and outs of inlining 134 条款31:将文件间的编译依存关系降至最低 140 minimize compilation dependencies between files 140 6 继承与面向对象设计 149 inheritance and object-oriented design 149 条款32:确定你的public继承塑模出is-a关系 150 make sure public inheritance models "is-a " 150 条款33:避免遮掩继承而来的名称 156 avoid hiding inherited names 156 条款34:区分接口继承和实现继承 161 differentiate between inheritance of interface and inheritance of implementation 161 条款35:考虑virtual函数以外的其他选择 169 consider alternatives to virtual functions 169 条款36:绝不重新定义继承而来的non-virtual函数 178 never redefine an inherited non-virtual function 178 条款37:绝不重新定义继承而来的缺省参数值 180 never redefine a function's inherited default parameter value 180 条款38:通过复合塑模出has-a或"根据某物实现出" 184 model "has-a" or "is-implemented-in-terms-of" through composition 184 条款39:明智而审慎地使用private继承 187 use private inheritance judiciously 187 条款40:明智而审慎地使用多重继承 192 use multiple inheritance judiciously 192 7 模板与泛型编程 199 templates and generic programming 199 条款41:了解隐式接口和编译期多态 199 understand implicit interfaces and compile-time polymorphism 199 条款42:了解typename的双重意义 203 understand the two meanings of typename 203 条款43:学习处理模板化基类内的名称 207 know how to access names in templatized base classes 207 条款44:将与参数无关的代码抽离templates 212 factor parameter-independent code out of templates 212 条款45:运用成员函数模板接受所有兼容类型 218 use member function templates to accept "all compatible types " 218 条款46:需要类型转换时请为模板定义非成员函数 222 define non-member functions inside templates when type conversions are desired 222 条款47:请使用traits classes表现类型信息 226 use traits classes for information about types 226 条款48:认识template元编程 233 be aware of template metaprogramming 233 8 定制new和delete 239 customizing new and delete 239 条款49:了解new-handler的行为 240 understand the behavior of the new-handler 240 条款50:了解new和delete的合理替换时机 247 understand when it makes sense to replace new and delete 247 条款51:编写new和delete时需固守常规 252 adhere to convention when writing new and delete 252 条款52:写了placement new也要写placement delete 256 write placement delete if you write placement new 256 9 杂项讨论 262 miscellany 262 条款53:不要轻忽编译器的警告 262 pay attention to compiler warnings 262 条款54:让自己熟悉包括tr1在内的标准程序库 263 familiarize yourself with the standard library, including tr1 263 条款55:让自己熟悉boost 269 familiarize yourself with boost 269 a 本书之外 273 b 新旧版条款对照 277 索引 280 编辑本段 译者序 按孙中山先生的说法,这个世界依聪明才智的先天高下得三种人:先知先觉得发明家,后知后觉得宣传家,不知不觉得实践家。三者之中发明家最少最稀珍,最具创造力。正是匠心独具的发明家创造了这个花花绿绿的计算机世界。 以文字、图书、授课形式来讲解、宣扬、引导技术的人,一般被视为宣传家而非发明家。然而,有一类最高等级的技术作家,不但能将精辟独到的见解诉诸文字,又能创造新的教学形式,引领风骚,对技术的影响和对产业的贡献不亚于技术或开发工具的创造者。这种人当之发明家亦无愧矣。 Scott Meyers就是这一等级的技术作家! 自从1991年出版《Effective C++》之后,Meyers声名大噪。1996年的《More Effective C++》和1997年的《Effective C++》2/e以及2001年的《Effective STL》让他更上高楼。Meyers擅长探索编程语言的极限,穷尽其理,再以一支生花妙笔将复杂的探索过程和前因后果写成环环相扣故事性甚强的文字。他的幽默文风也让读者在高张力的技术学习过程中犹能享受“阅读的乐趣”——这是我对技术作家的最高礼赞。 以条款(items)传递专家经验,这种写作形式是否为Meyers首创我不确定,但的确是他造成了这种形式的计算机书籍写作风潮。影响所及,《Exceptional C++》、《More Exceptional C++》、《C++ Gotchas》、《C++ Coding Standards》、《Effective COM》、《Effective Java》、《Practical Java》纷纷在书名或形式上“向大师致敬”。 睽违8年之后《Effective C++》第三版面世了。我很开心继第二版再次受邀翻译。Meyers在自序中对新版已有介绍,此处不待赘言。在此我适度修改第二版部分译序,援引于下,协助读者迅速认识本书定位。 C++ 是一个难学易用的语言! C++ 的难学,不仅在其广博的语法,以及语法背后的语义,以及语义背后的深层思维,以及深层思维背后的对象模型;C++ 的难学还在于它提供了四种不同而又相辅相成的编程范型(programming paradigms):procedural-based, object-based, object-oriented, generics。 世上没有白吃的午餐!又要有效率,又要有弹性,又要前瞻望远,又要回溯相容,又要治大国,又要烹小鲜,学习起来当然就不可能太简单。在庞大复杂的机制下,万千使用者前仆后继的动力是:一旦学成,妙用无穷。 C++ 相关书籍车载斗量,如天上繁星,如过江之鲫。广博如四库全书者有之(The C++ Programming Language、C++ Primer、Thinking in C++),深奥如重山复水者有之(The Annotated C++ Reference Manual, Inside the C++ Object Model),细说历史者有之(The Design and Evolution of C++, Ruminations on C++),独沽一味者有之(Polymorphism in C++),独树一帜者有之(Design Patterns, Large Scale C++ Software Design, C++ FAQs),另辟蹊径者有之(Generic Programming and the STL),程序库大全有之(The C++ Standard Library),专家经验之累积亦有之(Effective C++, More Effective C++)。这其中“专家经验之累积”对已具 C++ 相当基础的程序员有着立竿见影的帮助,其特色是轻薄短小,高密度纳入作者浸淫C++/OOP多年的广泛经验。它们不但开展读者的视野,也为读者提供各种C++/OOP常见问题的解决模型。某些主题虽然在百科型C++ 语言书中也可能提过,但此类书籍以深度探索的方式让我们了解问题背后的成因、最佳解法,以及其他可能的牵扯。这些都是经验的累积和心血的结晶,十分珍贵。 《Effective C++》就是这样一本轻薄短小高密度的“专家经验累积”。 本中译版与英文版页页对译,保留索引,偶尔加上小量译注;愿能提供您一个愉快的学习。千里之行始于足下,祝愿您从声名崇隆的本书展开一段新里程。同时,我也向您推荐本书之兄弟《More Effective C++》,那是Meyers的另一本同样盛名远播的书籍。 侯捷 2006/02/15于台湾新竹 编辑本段 序言 1991年我写下《Effective C++》第一版。1997年撰写第二版时我更新了许多重要内容,但为了不让熟悉第一版的读者感到困惑,我竭尽所能保留原始结构:原先50个条款中的48个标题基本没变。如果把书籍视为一栋房屋,第二版只是更换地毯灯饰,重新粉刷一遍而已。 到了第三版,修缮工作进一步深入壁骨墙筋(好几次我甚至希望能够翻新地基)。1991年起C++ 世界经历了巨大变革,而本书目标——在一本小而有趣的书中确认最重要的一些C++ 编程准则——却已不再能够由15年前建立的那些条款体现出来。“C++ 程序员拥有C背景”这句话在1991年是个合理假设,如今C++ 程序员却很可能来自Java或C# 阵营。继承(inheritance)和面向对象编程(object-oriented programming)在1991年对大多数程序员都很新鲜,如今程序员已经建立良好概念,异常(exceptions)、模板(templates)和泛型编程(generic programming)才是需要更多引导的领域。1991年没人听过所谓设计模式(design patterns),如今少了它很难讨论软件系统。1991年C++ 正式标准才刚要上路,如今C++ 标准规范已经8岁,新版规范蓄势待发。 为了对付这些改变,我把所有条款抹得一干二净,然后问自己“2005年什么是对C++ 程序员最重要的忠告?”答案便是第三版中的这些条款。本书有两个新章,一个是资源管理(resource management),一个是模板编程(programming with templates)。实际上template(模板)这东西遍布全书,因为它们几乎影响了C++ 的每个角落。本书新素材还包括在exceptions(异常)概念下编程、套用设计模式、 以及运用新的TR1程序库设施(TR1于条款54描述)。本书也告诉大家在单线程系统(single-threaded systems)中运作良好但可能不适用于多线程系统(multithreaded systems)的某些技术和做法。本书半数以上内容是新的。在此同时第二版大部分基础信息仍然很重要,所以我找出一个保留它们的办法:你可以在附录B找到第二、第三两版的条款对应表。 我努力让本书达到我所能够达到的最佳状态,但这并不表示它已臻完美。如果你认为某些条款不适合作为一般性忠告,或你有更好的办法完成本书所谈的某件工作,或书中某些技术讨论不够清楚不够完全,甚或有所误导,请告诉我。如果你找出任何错误——技术上的、文法上的、排版印刷上的,不论哪一种——也请告诉我。我很乐意将第一位提出问题并吸引我注意的朋友加入下次印刷的致谢名单中。 即使本书条款个数扩充为55,这一整组编程准则还谈不上完备。然而毕竟整理出优良准则——几乎任何时间适用于任何应用程序的准则——比想象中困难得多。如果你有其他编程准则的想法或建议,我将乐以与闻。 我手上维护本书第一刷以来的变化清单,其中包括错误修订、进一步说明和技术更新。致 谢 《Effective C++》已经面世15年了,我开始学习C++ 则是在书写此书的前5年。也就是说 "Effective C++项目" 已经发展两个年代了。此期间我得益于数百(数千?)人的深刻知识、对我的建议与修正,以及偶发的一些目瞪口呆的事绩。这些人帮助我更加完善《Effective C++》,我要对他们全体表示感谢。 我已经放弃追踪“在哪儿学到什么”的历史,但永远记得有个公众信息来源不断带给我帮助:Usenet C++ newsgroups,特别是comp lang c++ moderated和comp std c++。本书许多——也许是大多数——条款得益于这些讨论群所突出的若干技术想法和后续调查与诊疗。 关于第三版新内容,Steve Dewhurst和我一起讨论了最初的条款名单。条款11中关于“藉由copy and-swap实现operator=”的构想来自Herb Sutter在此主题的作品,像是《Exceptional C++》(Addison-Wesley, 2000)条款13。RAII(见条款13)源自Bjarne Stroustrup的《The C++ Programming Language》(Addison-Wesley, 2000)。条款17背后的想法来自Boost shared_ptr网页上的“Best Practices”节区(http://boost org/libs/smart_ptr/shared_ptr htm#BestPractices),又得到Herb Sutter的《More Exceptional C++》(Addison-Wesley, 2002)条款21的琢磨。条款29强烈受到Herb Sutter在此主题上的广泛作品的影响,像是《Exceptional C++》条款8~19,《More Exceptional C++》条款17~23,以及《Exceptional C++ Style》(Addison-Wesley, 2005)条款11~13;David Abrahams帮助我更好地了解三个异常安全性保证。条款35的NVI 手法来自Herb Sutter写于《C/C++ Users Journal》2001年9月份的 "Virtuality" 专栏。同一条款中的Template Method和Strategy设计模式来自《Design Patterns》(Addison-Wesley, 1995),作者是Erich Gamma, Richard Helm, Ralph Johnson和John Vlissides。条款37所说的NVI使用手法,概念来自Hendrik Schober。David Smallberg 给了我动机在条款38写出一个定制型set 实现品。条款39提到EBO通常只在多重继承中才可用,这个构想源自David Vandevoorde和 Nicolai M Josuttis合著的《C++ Templates》(Addison-Wesley, 2003)。条款42中我对typename的最初理解来自Greg Comeau主持的 "C++ and C FAQ",Leor Zolman则帮助我认知我的最初了解并不正确(是我的错,和Greg无关)。条款46的本质源自于Dan Sak的谈话,"Making New Friends"。条款52末尾的那个想法“如果你声明一版operator new,你也应该声明其对应的delete伙伴”源自Herb Sutter的《Exceptional C++ Style》条款22。我从David Abrahams身上更多了解了Boost的检评过程(条款55有一份摘要)。 上面所说关于我向谁或从某处学习某一技术,并不必然表示谁或某处就是该技术的发明人或发表处。我的笔记还告诉我,我也使用了来自Steve Clamage, Antoine Trux, Timothy Knox和Mike Kaelbling的信息,可惜这份笔记没有提到如何以及在哪儿学到什么。 第一版草稿由Tom Cargill, Glenn Carroll, Tony Davis, Brian Kernighan, Jak Kirman, Doug Lea, Moises Lejter, Eugene Santos, Jr , John Shewchuk, John Stasko, Bjarne Stroustrup, Barbara Tilly和Nancy L Urbano共同检阅。我收到了一些改善建议并纳入后来刷次,这些建议来自Nancy L Urbano, Chris Treichel, David Corbin, Paul Gibson, Steve Vinoski, Tom Cargill, Neil Rhodes, David Bern, Russ Williams, Robert Brazile, Doug Morgan, Uwe Steinmüller,Mark Somer, Doug Moore, David Smallberg, Seth Meltzer, Oleg Shteynbuk, David Papurt, Tony Hansen, Peter McCluskey, Stefan Kuhlins, David Braunegg, Paul Chisholm, Adam Zell, Clovis Tondo, Mike Kaelbling, Natraj Kini, Lars Nyman, Greg Lutz, Tim Johnson, John Lakos, Roger Scott, Scott Frohman, Alan Rooks, Robert Poor, Eric Nagler, Antoine Trux, Cade Roux, Chandrika Gokul, Randy Mangoba和Glenn Teitelbaum。 第二版草稿由以下人士共同检阅:Derek Bosch, Tim Johnson, Brian Kernighan, Junichi Kimura, Scott Lewandowski, Laura Michaels, David Smallberg, Clovis Tondo, Chris Van Wyk和Oleg Zabluda。我收到来自以下人士的意见并因此对新刷有所帮助:Daniel Steinberg, Arunprasad Marathe, Doug Stapp, Robert Hall, Cheryl Ferguson, Gary Bartlett, Michael Tamm, Kendall Beaman, Eric Nagler, Max Hailperin, Joe Gottman, Richard Weeks, Valentin Bonnard, Jun He, Tim King, Don Maier, Ted Hill, Mark Harrison, Michael Rubenstein, Mark Rodgers, David Goh, Brenton Cooper, Andy Thomas-Cramer, Antoine Trux, John Wait, Brian Sharon, Liam Fitzpatrick, Bernd Mohr, Gary Yee, John O'Hanley, Brady Patterson, Christopher Peterson, Feliks Kluzniak, Isi Dunietz, Christopher Creutzi, Ian Cooper, Carl Harris, Mark Stickel, Clay Budin, Panayotis Matsinopoulos, David Smallberg, Herb Sutter, Pajo Misljencevic, Giulio Agostini, Fredrik Blomqvist, Jimmy Snyder, Byrial Jensen, Witold Kuzminski, Kazunobu Kuriyama, Michael Christensen, Jorge Yá?ez Teruel, Mark Davis, Marty Rabinowitz, Ares Lagae和Alexander Medvedev 第三版早期部分草稿由以下人士共同检阅:Brian Kernighan, Angelika Langer, Jesse Laeuchli, Roger E Pedersen, Chris Van Wyk, Nicholas Stroustrup和Hendrik Schober。完整草稿由以下人士共同检阅:Leor Zolman, Mike Tsao, Eric Nagler, Gene Gutnik, David Abrahams, Gerhard Kreuzer, Drosos Kourounis, Brian Kernighan, Andrew Kirmse, Balog Pal, Emily Jagdhar, Eugene Kalenkovich, Mike Roze, Enrico Carrara, Benjamin Berck, Jack Reeves, Steve Schirripa, Martin Fallenstedt, Timothy Knox, Yun Bai, Michael Lanzetta, Philipp Janert, Guido Bartolucci, Michael Topic, Jeff Scherpelz, Chris Nauroth, Nishant Mittal, Jeff Somers, Hal Moroff, Vincent Manis, Brandon Chang, Greg Li, Jim Meehan, Alan Geller, Siddhartha Singh, Sam Lee, Sasan Dashtinezhad, Alex Marin, Steve Cai, Thomas Fruchterman, Cory Hicks, David Smallberg, Gunavardhan Kakulapati, Danny Rabbani, Jake Cohen, Hendrik Schober, Paco Viciana, Glenn Kennedy, Jeffrey D Oldham, Nicholas Stroustrup, Matthew Wilson, Andrei Alexandrescu, Tim Johnson, Leon Matthews, Peter Dulimov和Kevlin Henney。某些个别条款的草稿由Herb Sutter和Attila F Feher检阅。 检阅一份不够洗炼(而且可能尚未完成)的手稿是件吃力的工作,在时间压力之下进行只会使得它更困难。我要感谢这么多人愿意为我做这件事。 如果对讨论素材缺乏背景,而又期望捕捉手稿中的每一个问题,检阅工作将更加困难。令人惊讶的是还是有人选择成为文字编辑。Chrysta Meadowbrooke是本书的文字编辑,她的周密工作揭露出许多逃过其他每一双眼睛的问题。 Leor Zolman在正式检阅前先以多种编译器检验所有代码,在我校订手稿之后又做一次。如果书中仍然存在任何错误,全是我的责任。Karl Wiegers和(特别是)Tim Johnson提供我快速而有帮助的反馈。
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页