# 指標 & 參照
## 2021/11/05 電算社第七堂社課
---
## 記憶體
----
是電腦儲存變數值的地方,
可以把它想像成是<font color="#FFF300">一個很長的紙帶</font>
上面有很多<font color="#FFF300">連續的格子</font>,每一個格子有<font color="#FFF300">連續的編號</font>
每個格子是 1 bit(0 or 1)
8 個 bit 組成 1 byte

---
## 指標 Pointer
----
指標是一種變數,
裡面存放一個變數的第一個記憶體位置(address)
可以視為它是<font color="#FFF300">"指向該變數的變數"</font>
----
宣告
```cpp=
int *ptr;
```
指向(賦值)
```cpp=
int a = 100;
int *ptr = &a; //宣告一個指標ptr,指向 a 的記憶體位置
//&是取址的意思,也就是取得a的記憶體位址
```
```cpp=
//或者是
int *ptr;
int b = 100;
ptr = &b; //宣告一個指標ptr,指向 b 的記憶體位置
```
----
取值
```cpp=
int a = 100;
int *ptr = &a;
cout << ptr << " 、 " << *ptr << endl;
//*ptr可以知道ptr指向的變數的值
//輸出結果 : a的記憶體位置 、 100
```
----
改值
```cpp=
int a = 100;
int *ptr = &a;
cout << ptr << " 、 " << *ptr << endl;
//輸出結果 : a的記憶體位置 、 100
*ptr = 110; //它會直接更動指向的變數(a)的值
cout << ptr << " 、 " << *ptr << endl;
//輸出結果 : a的記憶體位置 、 110
```
----
### 小差異(常用錯!!)
```cpp=
int a = 10, b = 20;
int *ptr = &a; //ptr這個指標指向a
ptr = &b; //現在改成指向b
*ptr = a;
//這個跟上一行不一樣,ptr仍舊指向b,但是b的值被改為與a相同
```
---
## reference(參照)
----
reference可以理解成是一個變數的<font color="#FFF300">別名</font>
它不像指標會儲存記憶體位置
他反而可以<font color="#FFF300">直接操控該變數</font>
----
```cpp=
int a = 10;
int &b = a;
//宣告一個reference b,指向a,想像它是a的綽號
```
----
應用
```cpp=
int a = 10;
int &b = a;
cout << a << ' ' << b << endl; //輸出 10 10
b = 100; //會間接讓a也變成100
cout << a << ' ' << b << endl; //輸出 100 100
```
---
## 指標 vs 參照
----
直接看例子吧:D
----
```cpp=
#include <iostream>
using namespace std;
int main(){
//宣告
int a = 2;
int *pt = &a; // pt是一個指標變數,存取a的記憶體位置
int &r = a; // r是一個參照,為a的綽號
cout << a; // 2
cout << &a; // a的記憶體位置
cout << *&a; // 2
cout << pt; // a的記憶體位置
cout << &pt; // pt的記憶體位置
cout << *pt; // 2
cout << r; // 2
cout << &r; // a的記憶體位置
cout << *&r; // 2
return 0;
}
```
---
## 函式
## call by value & call by address & call by reference
---
### call by value
----
call by value就是傳值的意思,
<font color="#FFF300">呼叫變數時是複製一份數值,</font>
而非將記憶體連動過去
上一堂課中的那些引數都是 call by value
----
Example:
```cpp=
#include <iostream>
using namespace std;
void add(int value_a){
value_a++;
cout << value_a << '\n'; //2
}
int main(){
int a = 1;
add(a);
cout << a; // 1
return 0;
}
//上面的函式將a的數值複製一份到value_a,所以改變value_a的值並不會改變a的值
```
----
那如果想<font color="FFF300">改變值</font>的話該怎麼辦呢
這時候就必須<font color="#FFF300">回傳</font>
----
```cpp=
#include <iostream>
using namespace std;
int add(int value_a){
value_a++;
return value_a;
}
int main(){
int a = 1;
cout << add(a); // 2
return 0;
}
```
---
### call by address
----
call by address 就是傳指標,傳到函式時用指標連動到原先的變數,所以改變指標時原先的值也會改變
----
Example:
```cpp=
#include<iostream>
using namespace std;
void add(int *pointer_a){
(*pointer_a)++; //記得加(),因為 ++ 的優先度高於取值(*)
}
int main(){
int a = 1;
add(&a); //記住要傳的是 a 的位置
cout << a; // 2
return 0;
}
//pointer_a 是個指向 a 記憶體位置的指標
//所以改變 pointer_a 的值 a 也會變
```
---
### call by reference
----
call by reference就是傳參照,呼叫變數時會直接連動記憶體,所以改變值時原變數的值也會跟著改變
----
Example:
```cpp=
#include <iostream>
using namespace std;
void add(int &reference_a){
reference_a++;
}
int main(){
int a = 1;
add(a);
cout << a; // 2
return 0;
}
//reference_a和a的記憶體位置是共用的
//所以改變reference_a的值也就改變了a的值
```
---
### 小練習
----
試著做出一個可以調換數值的函式吧,規定此函式回傳值必須為void,且輸出必須放在main函式中
----
輸入說明:輸入兩個數a, b
輸出說明:輸出a, b調換數值後的結果
範例輸入:1 2
範例輸出:2 1
----
我是防雷頁:D
----
常見錯誤
```cpp=
#include <iostream>
using namespace std;
void swap(int a, int b){
int t = a;
a = b;
b = t;
}
int main(){
int a, b;
cin >> a >> b;
swap(a, b);
cout << a << b;
return 0;
}
//call by value的函式會複製一份數值進去函式,所以不會改變原來的值
```
----
解答(call by address)
```cpp=
#include <iostream>
using namespace std;
void swap(int *a, int *b){
int t = *a;
*a = *b;
*b = t;
}
int main(){
int a, b;
cin >> a >> b;
swap(&a, &b);
cout << a << ' ' << b;
return 0;
}
```
----
解答(call by reference)
```cpp=
#include <iostream>
using namespace std;
void swap(int &a, int &b){
int t = a;
a = b;
b = t;
}
int main(){
int a, b;
cin >> a >> b;
swap(a, b);
cout << a << ' ' << b;
return 0;
}
```
{"metaMigratedAt":"2023-06-16T12:35:04.444Z","metaMigratedFrom":"YAML","title":"指標 & 參照","breaks":true,"slideOptions":"{\"transition\":\"slide\",\"theme\":null}","contributors":"[{\"id\":\"4f731eff-9d88-41f4-af56-2e3e02f20cfc\",\"add\":1814,\"del\":47},{\"id\":\"9e7d687a-83f2-4e8a-8ee6-8846394e69a5\",\"add\":26,\"del\":16},{\"id\":\"68c94489-3c2e-4879-b847-e982f360b03c\",\"add\":2389,\"del\":210},{\"id\":\"efc43b79-1b19-4cb1-9b18-ce50fad56214\",\"add\":384,\"del\":7}]"}