---
# System prepended metadata

title: Cpp-0-1-Resource
tags: [learning]

---

# 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