本文介紹了設計 Header files 應該要注意的眉眉角角。
這些須注意事項主要是參考 Google C++ Style Guide 以及我個人開發系統程式的經驗。
所有標頭檔都應該符合 Self-contained。
也就是說,假設使用者要引入 A 標頭檔,無須引入 B, C, D 等 A 使用到的相依標頭檔。
因此,開發者在設計標頭檔時應自行插入該檔案所需要的所有標頭檔。
承接上面提到的 Self-contained Headers,我們可以思考一下:
假設我今天使用到了 A 和 B 標頭檔,但兩者都使用了 C 標頭檔,這樣會不會出現重複載入的問題呢?
ISO/IEC 14882 是 C++ 程式語言的標準,這類的規格書會規範程式語言的特性和語法,方便不同開發團隊實作適用 C++ 的編譯器專案。
至於 C++ 11 (ISO/IEC 14882:2011) 則是 ISO/IEC 14882 的第三個版本,前兩個版本分別是:
從時間線上可以觀察出 C++ 的第二版與第三版標準間隔了好一段時間,也因為這個緣故,C++ 11 更新了非常多個功能,所以又有人稱 C++ 11 與之後的版本是 Modern C++。
至於本文要介紹的功能則會以筆者自己刷題要用的功能為主,其他的功能就…再看看吧 XD
C++ 11 提供了 Range based 的 For 迴圈,如果我們使用一般的迴圈尋訪一個陣列或是 STL Container,會需要這樣做:
使用 Range based for-loop 以後,程式碼可以這樣寫:
我們可以發現,上面的範例省去了很多的條件判斷式。不只如此,它還幫我們做了 Dereference 的操作,讓開發者可以少打很多程式碼 XD
不過到目前為止,都還沒有提到 STL,所以我們先用基礎型別來作範例吧!
遍歷陣列:
遍歷並修改陣列元素:
如果將上面提供的範例執行,my_array
的元素並不會被加倍,如果要達到預期目標,我們需要將他的 Reference 傳入:
標準模板庫 (Standard Template Library, STL)
Vector 是強化版的 Array ,提供了更多靈活的成員函式, STL 的好處就是不用自己動手造輪子,就有一些增強型的資料結構可以使用。
Vector 有以下特性:
簡單地講,指標基本上只是在記錄該變數(物件、資料…etc)在記憶體中的位址;iterator 比較抽象,它算是抽象過後的拜訪規則。
而 iterator 比較像是「我要怎麼依序拿到這一串資料中的每個資料」,最簡單的例子是連續陣列 (array),但這個很簡單,語法上你只要透過 index 就可以依序拿;但很多資料結構並不是用這麼簡單的方式來排列,iterator 就變成像是一個共通的語言,讓程式語法在依序拿資料時有個一樣的寫法。
跟 vector 差不多,可是多了 push_front()
可以用:
STL 的 list 是 doubly linked-list:
Doubly linked-list 的特性如下:
接下來的 STL Container(包括 Set)都是屬於 Associated STL Container,也就是 key-value 對應關係的資料結構實作。
O(n)
,worst case 為 O(1)
搭配 C++ 11 特性與 STL 的 Vector 排序範例:
左值與右值的根本區別在於是否允許取位址 &
運算子獲得對應的記憶體位址。
在 C++ 03 以前的標準定義了在表達式中左值到右值的三類隱式自動轉換:
i
在表達式 i+3
https://cat.chriz.hk/2022/01/c-reference-collapsing-forwarding.html
在傳統的 C/C++ 程式中,使用動態分配記憶體需要留意已分配記憶體是否會在正確的時間點回收。
如果在記憶體使用完畢後沒有將其釋放,而指向這塊記憶體的指標又被用於指向其他記憶體位址。這樣一來,程式便無法取得已分配的記憶體位址,無法得知位址也就代表我們沒有能力去回收這塊已分配的記憶體,這樣的情況便是 Memory leak。
Smart pointer 的出現幫助我們解決了這個叫人頭痛的困擾。
轉移擁有權有兩種方法:
release()
成員函式tea_owner.release()
呼叫的是 std::unique_ptr
的成員函式。
tea_owner->HitByCCPDirtyTrick()
會呼叫到 TeaShopOwner
的成員函式。
方法二: 使用 std::move()
想法: