[2017.02.04] C++學習記錄(1)
編程式語言的目的是幫助程式設計師以程式碼的形式表述ideas。程式語言一方面為程式設計師提供一組關於可以做什麼的抽象,另一方面為程式設計師提供可以被機器執行的輪子。C++程式語言,支援4種程式設計正規化:過程式(Procedural Programming,主要集中在過程和合適的資料結構)、資料抽象(Data abstraction,主要表現為設計抽象介面隱藏具體實現細節)、面向物件程式設計(Object-oriented programming,主要集中在設計、實現和使用類繼承結構,提供執行時多型性)和泛型程式設計(Generic programming,主要集中在設計、實現和使用泛型演算法,提供編譯時多型性)。
C++廣泛應用於教學和科學研究,雖然不是“最好”的語言,但是它是一門可以伴隨著成長的語言,有如下特點:
Sufficiently clean for successfully teaching basic design and programming concepts
Sufficiently comprehensive to be a vehicle for teaching advanced concepts and techniques
Sufficiently realistic, efficient, and flexible for demanding projects
Sufficiently commercial to be a vehicle for putting what is learned into nonacademic use
Sufficiently available for organizations and collaborations relying on diverse development and execution environments
在學習C++的時候,一是要關注基本概念(fundamental concepts),如型別安全(type safety)、資源管理(resource management)和不變數(invariants)等;二是要學習一些程式設計技術,如資源管理的實現、演算法中的迭代器的使用、設計模式(可複用面向物件軟體的基礎)等。切記沉浸在語言的細節中。學習語言的目的是為了更加高效設計和實現新的系統並維護舊的工程。因此評判鑑定不同的語言和設計技術,比理解所有的細節更加重要。細節的熟練掌握需要時間的沉澱和實踐打磨。
C++語言有幾個不同獨立版本的實現,如Microsoft自家在VisualStudio中的實現,GNU的MinGW實現等。每種版本都有自己對C++標準的解釋和一些偏見,所有學習的時候,多多綜合參考各自的manuals、online resources等,以期達到更加全面的理解。
學好一門程式語言,就如同學會寫作一樣。需要我們知道自己想要說什麼(Know what you want to say)並且多加練習和模仿名家作品(Practice and imitate good writing)。大道至簡卻也知易行難。
一些C++學習和使用建議:
- C++不僅僅是C的超集。C++雖然可以像C那樣使用,但是在維護和效能上屬於這是未達到標準的行為。為了真正發揮C++優勢,我們需要採用不同的設計和實現風格(implementation styles)。C++提供了有用的語言特性,就不必再使用C的風格(如字串賦值時使用 = 而不是strcpy(),字串比較時使用==而不是strcmp())。
- C++中儘量少用巨集替換(macro substitution),雖然巨集替換減少了工作量,但是不利於靜態型別檢查,不便於除錯和維護。可以使用const/constexpr/enum/enum class來定義常量(manifest constants),使用inline減少函式呼叫的開銷,使用templates來定義相似的函式和型別,使用namespace避免名稱衝突。
- 不要使用原生的malloc/free,使用new/delete結合智慧指標unique_ptr/shared_ptr/weak_ptr等實現記憶體管理;使用vector等類庫替換realloc等操作。
- 避免隱式型別轉換,使用顯式的有名轉換(explicit named casts),如使用static_cast運算子。
- 使用容器和演算法,不要認為辛苦地編寫C風格的程式碼就比使用STL庫更加有效率,通常吃力不討好。
- 使用constructor/destructor pairs 簡化資源管理操作,常使用RAII技術。
- 儘量使用久經考驗的標準庫設施而不是個人開發的程式碼,以增強程式碼複用性和可維護性。
- 當錯誤不能夠被區域性程式碼處理時,使用exception而不是error。
- 使用移動語義(move sematics)避免大物件的值拷貝。
- 使用智慧指標代替原生指標,不要混用智慧指標和原生指標。
- 使用模板維護靜態型別安全檢查和實現編譯時多型。
- 不要過度抽象(overabstract),避免使用不必要的類繼承。
- 使用區域性變數,避免使用全域性變數,最小化指標的使用場合。
- Keep simple things simple (without making complex things impossible).
C++的history/timeline/language features/library facilities。
經過幾十年發展,C++的語言標準也在不停的進化,我們想要做一個合格的碼農,也需要跟上語言標準的步伐。學習新技術不是為了學習而學習,而是為了使用新技術解決了過往技術的痛點。如今C++11已經提出了五六年了,新版本C++14/17也近在眼前,如果我們還僅僅停留在C++98而對新技術無動於衷,未免有點故步自封了。學習和使用新版本中的語法特性,使得設計和程式設計時更加現代化。
C++11的目標:
- Make C++ a better language for systems programming and library building.
- Make C++ easier to teach and learn.
C++11 的 new features:
- Control of defaults: =delete and =default.
- Deducing the type of an object from its initializer, auto.
- Generalized constant expression evaluation (including literal types), constexpr.
- In-class member initializers.
- Inheriting constructors.
- Lambda expressions, a way of implicitly defining function objects at the point of their use in an expression.
- Move semantics, a way of transmitting information without copying.
- A way of stating that a function may not throw exceptions noexcept.
- A proper name for the null pointer.
- The range-for statement.
- Override controls: final and override.
- Type aliases, a mechanism for providing an alias for a type or a template. In particular, a way of defining a template by binding some arguments of another template.
- Typed and scoped enumerations: enum class.
- Universal and uniform initialization (including arbitrary-length initializer lists and protection against narrowing).
- Variadic templates, a mechanism for passing an arbitrary number of arguments of arbitrary types to a template.
...
C++11的library facilities
- Hashed containers, such as unordered_map.
- The basic concurrency library components, such as thread, mutex, and lock.
- Launching asynchronous computation and returning results, future, promise, and async().
- The garbage collection interface.
- A regular expression library, regexp.
- A random number library.
- A pointer for simply and efficiently passing resources, unique_ptr.
- A pointer for representing shared ownership, shared_ptr.
- The tuple library.
- The general bind().
- The function type for holding callable objects.
學習C/C++的書單列表
- The C Programming Language
- The C++ Programming Language
- C++ Primer
- Computer Systems: A Programmer's Perspective
- Code Complete
- Design Patterns:Elements of reusable object-orientd- software
- Python原始碼剖析
- STL原始碼剖析
- 冒號課堂
- Algorithms
- Compilers:Principle,Techniques and Tools
C/C++程式設計入門和進階專案
- 字串類
- 多執行緒程式設計:多執行緒IO環形佇列緩衝大檔案英文單詞詞頻統計
- 多執行緒程式設計:訊息傳遞同步操作的多執行緒銀行ATM模擬
- LevelDB原始碼閱讀
- Python原始碼剖析
- STL原始碼剖析
- Redis原始碼閱讀
面向物件程式設計和設計(Object oriented programming and design)的SOLID原則:
S:SRP,single responsibility principle,單一職責原則。一個類應該只有一個職責。
O:OCP,Open/Closed principle,開閉原則。一個軟體實體(類、模組、函式等)應該對拓展開放,對修改關閉。這樣可以不修改實體的原始碼而直接拓展它的行為。
L:LSP,Liskov substitution principle,里氏替換原則。 基類可以被子類替換而不產生型別錯誤。
I:ISP,Interface segregation principle,介面隔離原則。 多個特例化的介面優於一個通用的介面。對軟體進行解耦合,便於後期重構和維護。
D:DIP,Dependency inversion principle,依賴倒轉原則。高層模組不應愛依賴於底層模組,它們都應該依賴於抽象。抽象不依賴於細節,細節依賴於抽象。