# value & poionter & reference


## ***引用***

1. ***什么是引用***    
   
   - *reference 其实就是一个漂亮的 pointer*

2. ***引用的代码***
   
   - ```cpp
     int x = 0;
     int* p = &x; // p is a pointer to x
     int& p = x; // r is a reference to x
     int x2 = 5;
     
     r = x2;
     int& r2= r;
     ```
   
   - *`int*`是 pointer to int，`int&`是 reference to int，比如 `int* p = &x;` 我们会说指针p指向了x，而`int& r = x;`我们会说 r 代表了 x，其实r里面有一个指针指向了x ，r 只要代表了 x 就不可以代表别的变量，pointer不同，pointer还可以指向别的变量*

3. ***假象***
   
   - *我们观察上面的 x 和 r的地址和大小，就发现 `sizeof(r) = sizeof(x)` `&x == &r` object 和其 reference的大小相同，地址也相同（但是都是假象）*

4. ***reference的常见用途***
   
   - ***reference一般不用在声明变量，而用在参数类型和返回类型的描述***
     
     ```cpp
     void func1(Cls* pobj) { pobj->xxx(); } // pass by pointer
     void func2(Cls obj) { obj.xxx(); } // pass by value
     void func3(Cls& obj) { obj.xxx(); } // pass by reference
     ```
     
     ```cpp
     Cls obj;
     func1(&obj);
     func2(obj);
     func(obj);
     ```
     
     *我们能发现 pass by pointer 跟其他的都不一样，而"value" "reference"被调用端的写法相同，调用端接口也相同*
     
     ***所以最好用 reference 不行的情况下 比如返回临时对象的情况下，用value***

## ***签名***

1. ***什么是签名***
   
   - *不含return type的函数部分叫做签名*
   
   - *如下述代码 他们的签名都是 `image(const double im)` 所以他们两者不能同时存在*
     
     ```cpp
     double image(const double& im) { ... }
     double image(const double im) { ... }
     ```
   
   - ***const 也算函数签名***

## ***指针和引用的区别***

1. *指针和引用都是内存地址的一个概念，区别就是指针是一个实体，引用是一个别名*
2. *指针他指向一个内存，在编译的时候会以 "指针名 - 指向的内存地址" 存入符号表，所以说 指针包含的内容是可以改变的，并且是可以 `const`修饰的，允许拷贝和赋值，甚至可以为空，`sizeof`得到的就是指针类型的大小*
3. *引用则就是相当于一个内存的别名，在添加到符号表的时候，是以 "引用变量名 - 引用对象的地址"添加到符号表中，符号表一经完成不能改变，所以引用必须而且只能在定义时被绑 定到一块内存上，后续不能更改，也不能为空，也没有 const 和非 const 区别*
4. *sizeof*
   - *sizeof 引用得到代表对象的大小*
   - *sizeof 指针得到的是指针本身的大小*
5. *参数传递*
   - *传指针的实质是传值，传递的值是指针的地址。指针需要被解引用后才可以对对象进行操作*
   - *传引用的实质是传地址，传递的是参数的地址。直接对引用进行的修改会直接作用到引用对象上*

## ***参数传递***

1. *pass by value*
   
   - *形参是实参的拷⻉，函数内部对形参的操作并不会影响到外部的实参*
   - *值传递过程中，被调函数的形式参数作为被调函数的局部变量处理，会在栈中开辟内存空间以存放由主调函数传递进来的实参 值，从而形成了实参的一个副本(替身)*
   - *值传递的特点就是被调函数对形式参数的任何操作都是作为局部变量进行的，不会影响主调函数的实参变量的值(形参指针变了，实参指针不会变)*

2. *pass by pointer*
   
   - *指针参数本质上就是一个值传递，他所传递的是一个地址值*
   - *当对地址值的指向操作时，就相当于对实参本身进行操作*

3. *pass by reference*
   
   - *被调函数的形式参数也作为局部变量在栈中开辟了内存空间，但是这时 存放的是由主调函数放进来的实参变量的地址*
   
   - *被调函数对形参(本体)的任何操作都被处理成间接寻址，即通过栈中存放的地址访问主调函数中的实参变量(根据别名找到主调函数中的 本体)*
     
     ***因此，被调函数对形参的任何操作都会影响主调函数中的实参变量***

4. *引用传递和指针传递是不同的*
   
   - *虽然他们都是被调函数栈空间上的一个局部变量，但是任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量，而对于指针传递的参数，如果改变被调函数中的指针地址，他将应用不到主调函数的相关变量。*
   - *如果想通过指针参数传递来改变主调函数中的相关变量(地址)，那就得使用指向指针的指针或者指针引用*

## ***野指针***

1. *什么是野指针*
   - *就是没有被初始化过的指针*
2. *如何避免野指针*
   - *在平时的编码中，养成定义指针后初始化或者使用智能指针的习惯*

## ***悬空指针***

1. *什么是悬空指针*
   - *是指针最初指向的内存已经被释放的一种指针*

