午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

Effective Modern C++筆記匯總

 mscdj 2017-10-30

從 2016 年 8 月份開始讀這本書,限于目前大陸這邊還沒有中文版,所以是一邊讀一邊翻譯,但是自己的英語水平很一般,所以并沒有以翻譯的角度來寫文章,怕自己的水平糟蹋了這本好書,所以基本上就是讀懂了書中的意思,然后按照自己的理解寫出來,截止 2017 年 6 月 5 號已經(jīng)全部完成,目前是第一版,自己還在不斷調(diào)整語句、格式和內(nèi)容。力求不誤導(dǎo)人。也希望廣大的 C++愛好者可以給我提出一些修改建議。

Effective Modern C++ 目錄

Item1 Understand template type deduction

Tips:
1. 在模版類型推到的時候,如果傳遞的參數(shù)是引用類型,那么可以看作是非引用類型的,也就是說類型的引用部分被忽略。
2. 當(dāng)對通用引用類型的參數(shù)進(jìn)行類型推導(dǎo)時,左值參數(shù)需要特殊對待。
3. 當(dāng)推導(dǎo)正常的參數(shù)類型時,const和volatile類型的參數(shù)會被忽略掉const和volatile部分。
4. 在模版類型推導(dǎo)時,如果參數(shù)是數(shù)組或是函數(shù)名會退化為指針,除非這些參數(shù)是用來初始化 引用的。

Item2 Understand auto type deduction

Tips:
1. auto類型推導(dǎo)通常和模版類型推導(dǎo)是一致的,但是auto類型推導(dǎo)對于{}會推導(dǎo)為std::initializer_list,但是模版類型無法對其進(jìn)行推導(dǎo)
2. auto對于函數(shù)返回值的類型推導(dǎo)和lambda參數(shù)類型推導(dǎo)時就是隱式的模版類型推導(dǎo),并不是auto類型推導(dǎo),對于{}無法進(jìn)行推導(dǎo)

Item3 Understand decltype

Tips:
1. decltype推導(dǎo)出來的類型幾乎總是和目標(biāo)類型是一致的
2. 對于類型為T的左值表達(dá)式來說,decltype總是推導(dǎo)成T&
3. C++14支持decltype(auto)聲明變量和auto類似,可以對初始值進(jìn)行類型推導(dǎo),但是遵循的是decltype的規(guī)則

Item4 Know how to view deduced types

Tips:
1. 類型推導(dǎo)可以借助于IDE,或者是編譯器的錯誤輸出以及Boost TypeIndex庫
2. 一些工具的類型推導(dǎo)結(jié)果可能是對我們所有幫助的,但是不一定是準(zhǔn)確的,因此理解C++的類型推導(dǎo)規(guī)則仍然是必不可少的

Item5 Prefer auto to explicit type declarations

Tips
1. auto變量必須初始化,可以緩解因為類型不匹配導(dǎo)致的可移植性或效率問題,可以緩解在重構(gòu)過程中需要顯示輸入很長的變量類型名稱。
2. auto類型的變量受制于Item2和Item6中提到的陷阱

Item6 Use the explicitly typed initializer idiom when auto deduces undesied types

Tips
1. 對于一些看不見的proxy類型,使用auto對這類初始化表達(dá)式進(jìn)行類型推導(dǎo)會推導(dǎo)出錯誤的類型
2. 通過顯示的類型初始化慣用法可以強制auto推導(dǎo)出目標(biāo)類型

Item7 Distinguish between () and {} when creating objects

Tips
1. {}初始化是最廣泛的初始化語法,它可以阻止窄化轉(zhuǎn)換,并且避免了C++最復(fù)雜的語法解析
2. 在構(gòu)造函數(shù)做函數(shù)重載的時候,{}會優(yōu)先匹配帶有std::initializer_list參數(shù)的版本,即使其他構(gòu)造函數(shù)看起來更匹配
3. 對與std::vector兩個參數(shù)的構(gòu)造函數(shù)來說,其{}和()兩種初始化方式有很大的不同
4. 在模版中對于{}和()初始化如何進(jìn)行選擇是一個挑戰(zhàn)

Item8 Prefer nullptr to 0 and NULL

Tips
1. 優(yōu)先使用nullptr替換0和NULL
2. 避免同時重載帶有整型參數(shù)和指針類型的參數(shù)

Item9 Prefer alias declarations to typedefs

Tips
1. typedef 不支持模版化,但是using的別名聲明可以
2. 模版別名避免了傳統(tǒng)的typedef帶來的::type后綴,以及在類型引用的時候需要的typename前綴
3. C++14給所有的C++11模版類型萃取提供了別名

Item10 Prefer scoped enums to unscoped enums

Tips
1. C++98種的枚舉眾所周知是無作用域限制的
2. C++11中的枚舉類是有作用域限制的,不能進(jìn)行隱式的類型轉(zhuǎn)換需要使用C++的類型cast進(jìn)行轉(zhuǎn)換
3. 無論是枚舉類還是傳統(tǒng)的枚舉類型都支持指定底層的存儲,對于枚舉類來說默認(rèn)的底層存儲類型是int,而傳統(tǒng)的枚舉類型其底層存儲是未知的,需要在編譯器進(jìn)行選擇
4. 枚舉類總是可以進(jìn)行前向聲明的,而枚舉類型則不行,必須是在明確指定其底層存儲的時候才能進(jìn)行前向聲明

Item11 Prefer deleted functions to private undefined ones

Tips
1. 優(yōu)先使用delete來刪除函數(shù)替換放在私有作用域中未定義的
2. 任何函數(shù)都可以被刪除,包括非成員函數(shù),模版實例化等

Item12 Declare overriding function override

Tips
1. 對于要重寫的函數(shù)添加override關(guān)鍵字,讓編譯器負(fù)責(zé)檢查
2. 成員函數(shù)的引用標(biāo)識符可以識別出(*this)的不同,是左值類型,還是右值類型

Item13 Prefer const_iterators to iterators

Tips
1. 優(yōu)先使用const_iterator替換iterator
2. 為了是代碼更通用,應(yīng)該優(yōu)先使用非成員函數(shù)版本的begin、end、cbegin、cend等

Item14 Declare functions noexcept if they won’t emit exception

Tips
1. noexcept 是函數(shù)接口的一部分,這意味著調(diào)用者會依賴它
2. 使用noexcept聲明的函數(shù)相比于沒有使用noexcept聲明的函數(shù)代碼更具可優(yōu)化性
3. noexpect對于move、swap、內(nèi)存分配函數(shù)、析構(gòu)函數(shù)等具有特別的價值
4. 大多數(shù)函數(shù)都是異常中立的而不是noexcept

Item15 Use constexpr whenever possible

Tips
1. constexpr對象是const,它的初始值是編譯期的
2. constexpr函數(shù)當(dāng)傳入的參數(shù)是編譯期值時可以產(chǎn)生編譯期的結(jié)果
3. constexpr對象和函數(shù)可以廣泛使用在非constexpr修飾的對象和函數(shù)上下文中
4. constexpr關(guān)鍵字是對象以及函數(shù)接口的一部分

Item16 Make const member functions thread safe

Tips
1. 為了讓const成員函數(shù)是線程安全的,除非你確定不會在并發(fā)環(huán)境中調(diào)用
2. 使用std::atomic變量可能會提供比mutex更好的性能,但是它僅僅適合操作單個變量和內(nèi)存位置的操作

Item17 Understand special member function generation

Tips
1. 編譯器可能會生成的特殊成員函數(shù)會有默認(rèn)構(gòu)造函數(shù)、析構(gòu)函數(shù)、拷貝操作、移動操作等
2. 僅僅當(dāng)類沒有顯式的聲明移動操作、拷貝操作和析構(gòu)函數(shù)的時候,編譯器才會生成默認(rèn)的移動構(gòu)造函數(shù)
3. 僅僅當(dāng)類沒有顯式的聲明拷貝構(gòu)造函數(shù)、或是聲明了移動構(gòu)造函數(shù)時編譯器才會生成默認(rèn)的拷貝構(gòu)造函數(shù),和拷貝構(gòu)造函數(shù)類似,僅僅當(dāng)類沒有顯式的聲明拷貝賦值操作符或是移動構(gòu)造操作符時編譯器才會生成默認(rèn)的拷貝賦值操作符,不建議在具有明確聲明的析構(gòu)函數(shù)的類中生成復(fù)制操作。
4. 成員函數(shù)模版不會阻止編譯器生成特殊的成員函數(shù)

Item18 Use std::unique_ptr for exclusive-ownership resource management

Tips
1. std::unique_ptr很小、很快、是一個只能移動的,獨占管理資源的智能指針。
2. 默認(rèn)情況看下資源的刪除使用的是delete,但是可以定制刪除器,有狀態(tài)的刪除器會導(dǎo)致std::unique_ptr對象的大小增長。
3. 將std::unique_ptr轉(zhuǎn)換為std::shared_ptr是很容易的

Item19 Use std::shared_ptr for shared-ownership resource management

Tips
1. std::shared_ptr提供了方便的方法進(jìn)行垃圾回收可以對任意共享資源的生命周期進(jìn)行管理。
2. 相比于std::unique_ptr,std::shared_ptr對象通常情況下要大兩倍,這是因為它要分配一個控制塊,該控制塊中包含了一個原子類型的引用計數(shù)、刪除器、弱引用計數(shù)等
3. 默認(rèn)的資源釋放是通過delete,但是std::shared_ptr支持自定義刪除器,并且刪除器的類型不影響std::share_ptr的類型和大小。
4. 避免從一個指針類型的變量創(chuàng)建std::shared_ptr

Item20 Use std::weak_ptr for std::shared_ptr like pointers that can dangle

Tips
1. std::weak_ptr可以探查std::shared_ptr指向的指針是否是懸掛指針
2. 使用std::weak_ptr的一些潛在的場景包括,對象緩存、觀察者模式、阻止std::shared_ptr的循環(huán)引用

Item21 Perfer std::make_unique and std::make_shared to direct use of new

Tips
1. 相比于直接使用new,make系列的函數(shù)消除了源代碼重復(fù)、提升了異常安全性,并且std::make_shared和std::allocate_shared生成的代碼更小更快
2. 對于希望自定義刪除器以及通過{}進(jìn)行初始值的設(shè)定時,不適合使用make系列函數(shù)
3. 對于std::shared_ptr來說有兩類場景不適合使用make系列函數(shù),第一個就是需要自定義管理內(nèi)存的,第二個就是管理大對象時,并且存在std::weak_ptr比std::shared_ptr生命周期更長的情況

Item22 When using the Pimpl, define specific member functions in the implementation file

Tips
1. Pimpl的慣用法通過減少類的使用者對類實現(xiàn)的編譯依賴從而縮小編譯所花費的時間
2. pImpl使用std::unique_ptr時,類的特殊函數(shù)聲明放在頭文件中,具體實現(xiàn)放在實現(xiàn)文件中的,避免了頭文件中包含了std::unique_ptr析構(gòu)相關(guān)的函數(shù),導(dǎo)致編譯錯誤
3. 上面的建議適用于std::unique_ptr,但是不適用于std::shared_ptr

Item23 Understand std::move and std::forward

Tips
1. std::move的實現(xiàn)其實是一個無條件將類型cast轉(zhuǎn)換為右值類型,就本身而言沒有移動任何東西
2. std::forward就是根據(jù)參數(shù)的類型有條件的進(jìn)行cast轉(zhuǎn)換,如果輸入的參數(shù)是一個右值就轉(zhuǎn)換為右值,否則就轉(zhuǎn)換為左值
3. 無論是std::move還是std::forward在運行時都沒有做任何事情

Item24 Distinguish universal references from rvalues reference

Tips
1. 如果一個模版函數(shù)的參數(shù)類型是T&&,并且T的類型是推導(dǎo)出來的,或者一個對象使用auto&&這樣的聲明,那么這個函數(shù)的參數(shù)和要聲明的對象都是通用引用類型
2. 如果類型的聲明不是type&&,或者沒有發(fā)生類型推導(dǎo),那么type&&表示的是一個右值引用
3. 如果通用引用初始化的時候傳入的是一個右值,那么就和右值引用一樣,如果傳入的是左值那么就喝左值引用是一樣的

Item25 Use std::move on rvalue reference, std::forward on universal references

Tips
1. 應(yīng)用std::move到右值引用,std::forward到通用引用
2. 對于右值引用和通用引用作為值從函數(shù)返回時本質(zhì)上都是做了相同的事情
3. 如果希望通過編譯器進(jìn)行返回值優(yōu)化,則不要將std::move或std::forward應(yīng)用到局部對象

Item26 Avoid overloading on universal references

Tips
1. 在通用引用上進(jìn)行重載,幾乎總是會導(dǎo)致通用引用重載的版本比預(yù)期被調(diào)用的次數(shù)更頻繁。
2. 完美轉(zhuǎn)發(fā)構(gòu)造函數(shù)是非常有問題的,因為它們通常比非const左值的拷貝構(gòu)造函數(shù)更好地匹配,并且可以劫持派生類對基類拷貝構(gòu)造和移動構(gòu)造函數(shù)的調(diào)用。

Item27 Familiarize yourself with alternatives to overloading on universal references
Item28 Understand reference collapsing
Item29 Assume that move operations are not present,not cheap,and not used
Item30 Familiarize yourself with perfect forwarding failure cases
Item31 Avoid default capture modes
Item32 Use Init capture to move objects into closures
Item33 Use decltype on auto&& parameters to std::forward them
Item34 Prefer lambdas to std::bind
Item35 Prefer task-based programming to thread- based
Item36 Specify std::launch::async if asynchronicity is essential
Item37 Make std::threads unjoinable on all paths
Item38 Be aware of varying thread handle destructor behavior
Item39 Consider void futures for one-shot event communication
Item40 Use std::atomic for concurrency, volatile for specific memory
Item41 Consider pass by value for copyable parameters that are cheap to move and always copied.
Item42 Consider emplacement instead of insertion

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多