# Cpp-0-1-Resource github 上看到的 [C++ 學習教材](https://github.com/AnkerLeng/Cpp-0-1-Resource/blob/master/%E7%AC%AC3%E9%98%B6%E6%AE%B5-C%2B%2B%E6%A0%B8%E5%BF%83%E7%BC%96%E7%A8%8B%20%E8%B5%84%E6%96%99/%E8%AE%B2%E4%B9%89/C%2B%2B%E6%A0%B8%E5%BF%83%E7%BC%96%E7%A8%8B.md),第 1,2 部分太簡單,我從第 3 開始看,已經很熟的會略過 ###### tags: `learning` ## Memory mapping model * 執行前 * 代碼區 * 指令 * 唯讀 * 共享 * 資料區 * constant data * static data * 執行後 * stack * local data * handle function * process manage * heap * allocate * free ## new operator * allocate * new * 要新空間同時會呼叫 constructor * malloc * 單純給出空間 * free * delete * 釋放空間同時會呼叫 destructor * free * 單純釋放空間 ## reference ### reference VS pointer * reference * 別名 * 背後的實作用 const pointer * 必須初始化 * 無法更改別名 * 解釋: ```c++= int a; int &b = a; // b 不是 a 的副本, b 就是 a // 修改 b 等於 修改 a ``` * pointer * 變數地址 * 與 refernce 相比,要多一個 dereference ### reference 使用 * 簡化操作: * reference version ```c++ void swap(int &a, int &b) { int tmp = b; b = a; a = tmp; } int main() { int a = 1; int b = 2; swap(a, b); } ``` * pointer version ```c++ void swap(int *a, int *b) { int tmp = *b; *b = *a; *a = tmp; } int main() { int a = 1; int b = 2; swap(&a, &b); } ``` * as a function return value * 別回傳 local value * function 做為 left value ,猜測可能是 function 調用等同於別名,對其賦值等同對別名賦值 ```c++ int &foo() { static int a; a = 10; return a; } int main() { int b = foo(); foo() = 100; } ``` ### 本質 前面提過,基本就是 compiler 會把他弄成 constant pointer ,對別名操作實際上都是透過這個 const. pointer ```c++ // compiler 自動將其改為 int* const ref = a void foo(int &a) { a = 0xdeadbeef; } int main() { int a = 10; // compiler 修正為 int const *ref = &a; int &ref = a; // *ref = 100; ref = 100; foo(a); } ``` ### const reference 主要是用來防止操作錯誤,具體不表 ## class ### class member 權限問題 cpp class 內主要有三種權限: * public * 大家都可以存取、使用 * private * 只有內部 function 可以使用 * protected * 只有內部 function 和繼承的 class 可以在內部使用 所以說 protected 可以算是追加繼承版本的 private (之前一直沒弄懂) ### constructor and destructor * constructor/destructor * 負責初始化/清理 * 沒有實作則編譯器提供空實作 * destructor 會自己呼叫 * constructor * 同 class name * 可以 overloading * 沒有 return value, 也沒有 void * 只會 call 一次 * 直接建立 class 則 constructor 會自動呼叫 * destructor * ~class_name() * 沒有 overloading * 沒有 return value, 也沒有 void * 只會 call 一次 ### constructor 分類 * 依參數分類 * 無參數 * 可以自己實作 * 沒有實作則由編譯器提供 * 有參數 * 就是有參數... * 依類型分類 * 普通類型 * 上面那種就是普通類型 * 拷貝類型 * 參數為同 class 的 object ```c++ class Obj { Obj(const Obj &o2){member = o2.member;} }; ``` ### constructor 調用方式 * 無參數調用 ```c++ Object o1; Object o1 = Object(); ``` 原先以為 `Object o1()` 也是無參數調用,結果什麼鬼也沒發生,看來應該不是... * 括號法 ```c++ Object o1(1); ``` * 顯示法 ```c++ Object o1 = Object(1); ``` 根據資料上顯示 Object(1) 是匿名 object 結束後馬上進行 destructor 但是在實驗上反而是直接就轉成有參數的括號法,不知道是不是編譯器太聰明... * 轉換法 ```c++ Object o1 = 10; Object o1 = o2; ``` 調用 copy constructor 將 o2 的內容當作 o1 的初始 ### copy constructor 調用 * 用已創建的對象來初始化 ```cpp Object obj1(10); Object obj2 = obj1; ``` 或者 ```cpp Object obj1(10); Object obj2(obj1); ``` 兩種皆屬於用 copy constructor 來初始化新 object > 以前不知道有第二種 call 法... > **注意!以下這種不是 copy constructor** ```cpp Object obj1(10); Object obj2; obj2 = obj1; ``` 要記住無論是 copy constructor 還是一般 constructor 都只會調用一次!所以上面的例子是已經調用無參數的 constructor ,後面就是一般的賦值而已 * 把 object 當作參數傳遞 ```cpp void dowork(Object o) {} int main() { Object o1; dowork(o1); } ``` 猜測這是因為參數是 object 的 copy ,所以這邊實際上是 `Object o = o1` ,那理所當然最後 dowork() 結束也會 call o 的 destructor * 把 object 當作回傳值 因為是 local 變數傳出來當作 copy constructor 所以沒關係 ```cpp Object dowork() { Object oo(10); return oo; } int main() { Object o1 = dowork(); } ``` 不過在 local 測試的時候好像會直接 call 有參數的 constructor ,而不是 copy constructor ### 編譯器對於 constructor 的提供機制 * 無任何 constructor * 提供無參數 constructor * 提供 copy constructor * value copy * 有參數 constructor * 不提供無參數 constructor * 強行調用會出錯 * 提供 copy constructor * value copy * 有 copy constructor * 不提供無參數 constructor * 強行調用會出錯 * 不提供有參數 constructor * 強行調用會出錯 簡單講層級就是 copy constructor -> 有參數 constructor -> 無參數 constructor 另外 destructor 不管怎樣都會默認提供,**若有指標的話建議自己管理 destructor** ### Shallow copy VS Deep copy * shallow copy * 單純的把值複製過去 * 若有 pointer 則兩個 class 的 pointer member 會一樣 * 通常用在只有普通的值的 class * deep copy * 重新 allocate 一個空間再把值複製過去 * 有涉及 pointer 之類的使用 常見的錯誤作法: ```cpp class Object { public: Object(){int *arr = new int[10];} //... ~Object(){delete arr;} private: int *arr; }; int main() { Object o1; Object o2 = o1; } ``` o2 離開會先 call destructor , delete 掉 arr ,而 o1 call destructor 也會 delete arr ,兩者因為沒有另寫 copy constructor ,故兩個 arr 會是一樣的,這樣就造成了 double free ### 列表初始化 就是個方便初始化的語法糖而已... ```cpp class Obj { public: Obj(): a(1), b(2), c(3){}; private: int a, b, c; } ``` ### class member 為 class class member 可以是另一個 class 這個沒啥問題,一個比較值得關注的問題是:是 class 先建立還是 member class 先建立? 根據資料和實驗結果是先到 class constructor 但是接著執行 member class constructor 然後才是 class construcotr 順序: class member constructor -> class constructor destructor 的部分則是相反 ### static class member * static member variable * 所有 class 共用變數 * 存放於非 class 內 * 宣告於 class , 初始化於 class 外 * 若初始化於 class 內被當作 const * static member function * 所有 class 共用 function * **static function 僅能 access static variable** ### class model * this pointer * this == current object pointer