---
# System prepended metadata

title: C++ pointer

---

# C++ pointer
reference Youtube tutorial: https://www.youtube.com/watch?v=2R5cjpi9Fzw&t=3842s

## overview
```
    int a = 7;
    int* a_p;    // _p represnt the pointer
    a_p = &a;    // use operator & to get the address from the var
    
    std::cout << a << std::endl;       //get 7
    std::cout << *a_p << std::endl;    //get 7, dereference - get the value of the pointed address
    
    std::cout << &a << std::endl;    // the address of the var a
    std::cout << a_p << std::endl;     // the value in a_p, the address of the a
```
* ```int* a_p``` or ```int *a_p```, 表示宣告一個var a_p,其是用來存資料結構為int的address
* ```&a```, &是一個operator，其用來取得所指到var的address
* ```&a_p```, 稱作**dereference**, 用來access a_p中所指地址的資料
* 其他
    * ```*```, 稱作asterisk
    * ```&```, 稱作ampersand

```
    int x= 7;
    // Pointer assigned to store address of x
    int* px= &(x);

    int** p_px = &px; // p_px is a pointer to an integer pointer

    // What happens if we dereference p_px
    // and change the value?
    **p_px = 77;
```
* 在這個範例中，pointer可以再指向pointer(可以好幾層)
* dereference時，有幾層就要加幾個*(否則可能得到一個address)
* 第幾層的pointer也要有對應多的*(每形成一層的pointer就是一個新的type，用```int*** *```指向```int***```)
* 好處，再之後多層datatype中會使用到(例如要指向一個array，而array本身就是一個pointers collection)

## dereference
access pointer中所指到address中的value
1. normal datatype dereference(```*```)
    * custom datatype也可以用這種方式access
    ```
        int a = 7;
        int* a_p = &a;

        std::cout << *a_p << std::endl;
        *a_p = 7;
    ```
2. custom datatype deference(```->```, arrow syntax): 
    ```
        struct person{
            string name;
            int age;
        };
        
        person henry;
        henry.name = "henry";
        henry.age = 26;
        
        person* henry_p = &henry;
        
        std::cout <<　henry_p->name  << henry_p->age << std::endl;  // by arrow
        std::cout <<　*henry_p.name  << *henry_p.age << std::endl;  // by asterisk
    ```
## pointer arithmetic
對pointer(address)最arithmetic operation(+, -, increment, decrement)
    ```
        int arr[4];

        std::cout << arr[0] << *(arr+0) << std::endl;
        std::cout << arr[1] << *(arr+1) << std::endl;
        std::cout << arr[2] << *(arr+2) << std::endl;
        std::cout << arr[3] << *(arr+3) << std::endl;
    ```
* 本身arr就是一個pointer，其中所含的address是```arr[0]```(array is the continuous block of memory)
* 對pointer var做算數```+```或```-```表示將pointer中address +/- **sizeof(datatype)**的距離到一個新的address
    * ie. pointer所指向address是100，並且對應到datatype是int(4 bytes)，則+1 pointer所指address會變成104；-1 pointer所指address會變成96...
* array中```arr[2]``` ```*(arr+2)```是相同意思

## pointer vs array
1. there are still some diference between pointer and array
    ```
        int arr[4];
        int* a_p;
        
        arr = a_p;        //not allowed !!!
        a_p = $arr[0];    //allowed
    ```
    * 雖然上面說arr中的aggress是arr的第一個element address(arr[0])，但其還是跟int* pointer有點不同，因此不可以直接assign一個int*到arr pointer
    * 但是我們可以把arr中的element之address assign給int* pointer
2. array do decay to pointer when we pass is as function parameter
    ```
        void printlen(int* arr){
            std::cout << sizeof(arr) <<std::endl;    // get 8(address length) not 4*100 
            // the arr be treat as the address of the array element arr[0]
        }
        int arr[100];
        printlen(arr);
    ```
    * when i pass pointers of array as parameters, array do decay to pointers
    * function不知道這個pointer多長(後面又串幾個element)
    * 如何在function中仍然把此pointer當作array用，多加入一個parameter告訴此array有多長
    
## use case
1. **share the value**, which all the pointer can access the same varible by its address. then when the value of the variable is modified all the pointers can access the latest value without re-copy the value from variable
2. use pointer as parameter in function
    * c/c++中，傳遞parameter到function中的方式是passed by copy，電腦會重新複製一份parameter中value到function中的local memory，這讓我們無法在function中修改parameter所對應到的變數(稱作pass by value)
        ```
            void to100(int a){
                a = 100;
            }
            int a = 10;
            to100(a);
            
            std::cout << a << std::endl;  // get 10 still
        ```
    * **pass by pointer**: 但如果使用pointer(也就是address)，雖然還是passed by copy來把value(address)複製到function的local memory，但我們可以透過dereference address來access到外面的變數。此外如果今天parameter是自訂抑或更大的datatype(struct, class,...)那直接copy value會造成很大的loading
        ```
            void to100(int* a){
                *a = 100;
            }
            int a = 10;
            to100(a);
            
            std::cout << a << std::endl;  // get 100 now !!!
        ```
## problem1 - memory leak
* 對nullptr deference會造成segmental fault!!!但是對已經不存在var之前的address deference則不會(只是會access亂碼之類的東西，因為內容已經被其他人修改了)
* tool - clang
    * 我們可以用更進階的compiler(clang)來幫助我們檢查memory leak
    ```clang++-10 -g -fsanitize=address leak.cpp -o prog; ASAN_OOPTIONS=detect_leaks=1 ./ptog``
* tool - address sanitizer
    * 幫助我們檢查memory leak
* tool - valgrind
    * 幫助我們檢查memory leak

## problem2 - dangling pointer
* 去access一個已經不存在的address
* 例如:
    * 在dereference ```a_p```時，雖然還是可以去access，但是由於現在```a_p```不在屬於function中local var的memory address，因此這過程中有可能造成此address被其他人修改，讀取到的東西會是亂碼之類的東西
    ```
        char* dandlingPointerFunction*(){
            char a = 'a';
            return &a;
        }
        
        int main(){
            char* a_p = dandlingPointerFunction*();
            std::cout << *a_p << std::endl;
            return 0;
        }
    ```

## double free
* new出來的address被多個pointer所sharing，很容易造成同個東西被delete兩次

## MEMORY MANAGEMENT
* 由c++官網所提供mamory management指南
![螢幕擷取畫面 (75)](https://hackmd.io/_uploads/BJ3T5U-xA.png)

# C++ smart pointer
