致謝
====
我在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