致谢
====
我在2009年开始着力于众所周知的C++0x(现在叫做C++11)。我给Usenet newsgroup `comp.std.c++`投递了一些问题,我非常感谢社区的成员(特别是Daniel Krügler)的帖子。最近几年,当我有关于C++11和C++14的问题时候,我转战[Stack Overflow](http://stackoverflow.com/),我同样受惠于这个社区带给我关于现代C++编程的一些理解。
2010年,我准备了一个关于C++0x的训练课程(最终以[Overview of the New C++](http://www.artima.com/shop/overview_of_the_new_cpp)一书出版)。包括那些材料和知识都归功于和Stephan T. Lavavej,
Bernhard Merkle, Stanley Friesen, Leor Zolman, Hendrik Schober, and Anthony
Williams的审阅。没有他们的帮助,我可能永远都不会搞出这本Effective Modern C++。这个标题来源于我的一些读者在2014年2月18日发布的blog回帖[“Help me name my
book”](http://scottmeyers.blogspot.com/2014/02/help-me-name-my-book.html),Andrei Alexandrescu([Modern C++ Design](http://erdani.com/index.php/books/modern-c-design/)的作者)祝福书的标题不要抄袭他的术语。
我没法确定出这本书的所有原始信息,但是相关的资源有着直接的影响。[条款4](DeducingTypes/4-Know-how-to-view-deduced-types.md)使用了一个由Stephan T. Lavavej和Matt P. Dziubinski建议在编译器中`coax`类型信息的未定义的模板,这也使得我对Boost.TypeIndex加以关注。在[条款5](auto/5-Prefer-auto-to-explicit-type-declarations.md)中,`unsigned std::vector<int>::size_type`的例子取自于2010年2月28日Andrey Karpov的文章[“In what way can C++0x standard help you eliminate 64-bit errors”](http://www.viva64.com/en/b/0060/)。`std::pair<std::string, int>/std::pair<const std::string, int>`的例子取自于Stephan T. Lavavej在Going Native 2012的talk[“STL11: Magic && Secrets”](http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/STL11-Magic-Secrets)。[条款6](auto/6-Use-the-explicitly-typed-initializer-idiom-when-auto-deduces-undesired-types.md)有感于Herb Sutter在2013年8月12日的文章[“GotW #94 Solution: AAA Style (Almost Always Auto)”](http://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/)。[条款9](MovingtoModernC++/9-Prefer-alias-declarations-to-typedefs.md)的灵感来源于2012年5月27号Martinho Fernandes的博客[“Handling dependent names”](http://flamingdangerzone.com/cxx11/2012/05/27/dependent-names-bliss.html)。[条款12](MovingtoModernC++/12-Declare-overriding-functions-override.md)的检查reference qualifiers的重定义是基于2014年1月14号Casey在Stack Overflow的这个问题[“What’s a use case for overloading member functions on reference qualifiers”](http://stackoverflow.com/questions/21052377/whats-a-use-case-for-overloading-member-functions-on-reference-qualifiers)的回答。我的[条款15](MovingtoModernC++/15-Use-constexpr-whenever-possible.md)的关于C++14对`constexpr`函数的扩展支持的信息来源于Rein Halbersma。[条款16](MovingtoModernC++/16-Make-const-member-functions-thread-safe.md)是基于Herb Sutter的C++ and Beyond 2012的演讲,“You don’t know `const` and `mutable`”。[条款18](SmartPointers/18-Use-std-unique_ptr-for-exclusive-ownership-resource-management.md)的建议工厂方法返回`std::unique_ptr`是基于Herb Sutter在2013年5月30号的文章,[“GotW# 90 Solution: Factories”](http://herbsutter.com/2013/05/30/gotw-90-solution-factories/)。在[条款19](SmartPointers/19-Use-std-shared_ptr-for-shared-ownership-resource-management.md)中,`fastLoadWidget`继承于Herb Sutter的Going Native 2013的演讲,[“My Favorite C++ 10-Liner”](http://channel9.msdn.com/Events/GoingNative/2013/My-Favorite-Cpp-10-Liner)。我在[条款22](SmartPointers/22-When-using-the-Pimpl-Idiom-define-special-member-functions-in-the-implementation-file.md)中关于`std::unique_ptr`的不完备类型的论断来自于Herb Sutter在2011年11月27号的文章,[“GotW #100: Compilation Firewalls”](http://herbsutter.com/gotw/_100/)和Howard Hinnant在2011年5月22号在Stack Overflow的[“Is std::unique_ptr<T> required to know the full definition of T?”](http://stackoverflow.com/questions/6012157/is-stdunique-ptrt-required-to-know-the-full-definition-of-t)的回答。在[条款25](RvalueReferencesMoveSemanticsandPerfectForwarding/25-Use-std-move-on-rvalue-references-std-forward-on-universal-references.md)中的矩阵加法运算的例子是基于David Abrahams的作品。JoeArgonne在2012年12月8日的对2012年11月30日发布的帖子[“Another alternative to lambda move capture”](http://jrb-programming.blogspot.com/2012/11/another-alternative-to-lambda-move.html)的评论是[条款32](LambdaExpressions/32-Use-init-capture-to-move-objects-into-closures.md)的在C++11中基于`std::bind`的模拟init捕捉的来源。[条款37](TheConcurrencyAPI/37-Make-std-threads-unjoinable-on-all-paths.md)的在`std::thread`的析构函数的隐式detach是取自于Hans-J. Boehm的2008年12月4日的paper,[“N2802: A plea to reconsider detach-on-destruction for thread objects”](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2802.html)。[条款41](Tweaks/41-Consider-pass-by-value-for-copyable-parameters-that-are-cheap-to-move-and-always-copied.md)最开始是来源于David Abrahams在2009年8月15日的博客帖子的讨论,[“Want speed? Pass by value”](http://web.archive.org/web/20140113221447/http:/cpp-next.com/archive/2009/08/want-speed-pass-by-value/)。关于只移动types deserve special treatment归功于Matthew Fioravante,关于基于赋值的copying stems来源于Howard Hinnant的评论。在[条款42](Tweaks/42-Consider-emplacement-instead-of-insertion.md)中,Stephan T. Lavavej和Howard Hinnant帮助我理解了emplacement和insertion函数的性能区别,Michael Winterberg带给我关于emplacement怎么导致内存泄露的问题,(Michael使用了Sean Parent的Going Native 2013的演讲,[“C++ Seasoning”](http://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning)作为应用来源)。Michael并且指出了emplacement函数是怎么使用直接初始化,而insertion函数是使用拷贝初始化。
对一本技术书籍的校审是一件需要耗费时间精力并且绝对重要的任务,我非常荣幸有这么多的人愿意做这些事情。关于Effective Modern C++全部的或者部分的校审来自于Cassio Neri, Nate Kohl, Gerhard Kreuzer, Leor Zolman, Bart Vandewoestyne, Stephan T. Lavavej, Nevin “:-)” Liber, Rachel Cheng, Rob Stewart, Bob Steagall, Damien Watkins, Bradley E. Needham, Rainer Grimm, Fredrik Winkler, Jonathan Wakely, Herb Sutter, Andrei Alexandrescu, Eric Niebler, Thomas Becker, Roger Orr, Anthony Williams, Michael Winterberg, Benjamin Huchley, Tom Kirby-Green, Alexey A Nikitin, William Dealtry, Hubert Matthews, and Tomasz Kamiński。并且我收到了一些读者通过[O’Reilly’s Early Release EBooks](http://shop.oreilly.com/category/early-release.do)和[Safari Books Online’s Rough Cuts](http://my.safaribooksonline.com/roughcuts)和我的博客([The View from Aristeia](http://scottmeyers.blogspot.com/))和电子邮件的反馈。我对这些人非常的感激。这本书有了他们的帮助而变的更好。我要特别感谢Stephan T. Lavavej和Rob Stewart,他们非常非常详细的标注让我怀疑他们在这本书上花的时间比我还多。对Leor Zolman也表示特殊的感谢,他不仅阅读了原稿,还对书中的所有示例代码做了double-check。
电子书的校审是Gerhard Kreuzer, Emyr Williams, and Bradley E. Needham做的.
我对书中的代码单行长度的显示限制在64个字母(这是和电子设备,设备方向切换和字体设置有关系的)是基于Michael Maher的提供。
Ashley Morgan Williams在Lake Oswego Pizzicato uniquely entertaining做好吃的晚餐(老子饿了,为了翻译没吃饭——译者注)。When it comes to man-sized Caesars, she’s the go-to gal.(我实在不知道这句是啥意思——译者注)
More than 20 years after first living through my playing author, my wife, Nancy L.Urbano, once again tolerated many months of distracted conversations with a cocktail of resignation, exasperation, and timely splashes of understanding and support. During the same period, our dog, Darla, was largely content to doze away the hours I spent staring at computer screens, but she never let me forget that there’s life beyond the keyboard. (这段描绘了非程序员的技术型作家的美好生活,和我们的反差太大我已无力翻译——译者注)
- 出版者的忠告
- 致谢
- 简介
- 第一章 类型推导
- 条款1:理解模板类型推导
- 条款2:理解auto类型推导
- 条款3:理解decltype
- 条款4:知道如何查看类型推导
- 第二章 auto关键字
- 条款5:优先使用auto而非显式类型声明
- 条款6:当auto推导出非预期类型时应当使用显式的类型初始化
- 第三章 使用现代C++
- 条款7:创建对象时区分()和{}
- 条款8:优先使用nullptr而不是0或者NULL
- 条款9:优先使用声明别名而不是typedef
- 条款10:优先使用作用域限制的enmu而不是无作用域的enum
- 条款11:优先使用delete关键字删除函数而不是private却又不实现的函数
- 条款12:使用override关键字声明覆盖的函数
- 条款13:优先使用const_iterator而不是iterator
- 条款14:使用noexcept修饰不想抛出异常的函数
- 条款15:尽可能的使用constexpr
- 条款16:保证const成员函数线程安全
- 条款17:理解特殊成员函数的生成
- 第四章 智能指针
- 条款18:使用std::unique_ptr管理独占资源
- 条款19:使用std::shared_ptr管理共享资源
- 条款20:在std::shared_ptr类似指针可以悬挂时使用std::weak_ptr
- 条款21:优先使用std::make_unique和std::make_shared而不是直接使用new
- 条款22:当使用Pimpl的时候在实现文件中定义特殊的成员函数
- 第五章 右值引用、移动语义和完美转发
- 条款23:理解std::move和std::forward
- 条款24:区分通用引用和右值引用
- 条款25:在右值引用上使用std::move 在通用引用上使用std::forward
- 条款26:避免在通用引用上重定义函数
- 条款27:熟悉通用引用上重定义函数的其他选择
- 条款28:理解引用折叠
- 条款29:假定移动操作不存在,不廉价,不使用
- 条款30:熟悉完美转发和失败的情况
- 第六章 Lambda表达式
- 条款31:避免默认的参数捕捉
- 条款32:使用init捕捉来移动对象到闭包
- 条款33:在auto&&参数上使用decltype当std::forward auto&&参数
- 条款34:优先使用lambda而不是std::bind
- 第七章 并发API
- 条款35:优先使用task-based而不是thread-based
- 条款36:当异步是必要的时声明std::launch::async
- 条款37:使得std::thread在所有的路径下无法join
- 条款38:注意线程句柄析构的行为
- 条款39:考虑在一次性事件通信上void的特性
- 条款40:在并发时使用std::atomic 在特殊内存上使用volatile
- 第八章 改进
- 条款41:考虑对拷贝参数按值传递移动廉价,那就尽量拷贝
- 条款42:考虑使用emplace代替insert