# C++ 指標與參考
[toc]
## 指標(Pointer)
C++ 的原生指標定義為:
```c=
#include <iostream>
int main(int argc, char** argv) {
int a = 6;
int* p = &a;
std::cout << "The value of variable a: " << a << std::endl;
std::cout << "The address of variable a: " << &a << std::endl;
std::cout << "The value of the referenced variable by pointer p: " << *p << std::endl;
std::cout << "The value of pointer p: " << p << std::endl;
std::cout << "The address of pointer p: " << &p << std::endl;
return 0;
}
```
> `*` 稱之為解引用運算元(dereference operator),在這邊 `&` 為取址運算元(address-of operator)
指標 `p` 本身儲存是所指向資料的記憶體位址,如果輸出 `p` 的話看到的只是指向資料的記憶體位址,必須搭配解引用運算元 `*p`,才能取得指標所指向的資料。
### Null Pointer
原生指標可以是 nullptr(建議不要使用 NULL),例如:
```c=
int* p = nullptr;
```
> 指標 p 的值會是 0x0000000,沒有任何記憶體位置可以參考,使用 `*p` 將會出錯哦。
### Void Pointer
沒有指定特定資料型態的指標,可以好處是可以自由切換資料型態,但輸出時需要轉型。
```cpp=
#include <iostream>
int main(int argc, char** argv) {
int a = 5;
char e = 'e';
void* p;
p = &a;
std::cout << "The value of the referenced variable by pointer p: " << *static_cast<int*>(p) << std::endl;
std::cout << "The value of pointer p: " << p << std::endl;
std::cout << "The address of pointer p: " << &p << std::endl;
p = &e;
std::cout << "The value of the referenced variable by pointer p: " << *static_cast<char*>(p) << std::endl;
std::cout << "The value of pointer p: " << p << std::endl;
std::cout << "The address of pointer p: " << &p << std::endl;
return 0;
}
```
### 複雜指標
```cpp=
int a = 5; // 一般變數
int* b = &a; // 指向 int 的指標
int** c = &b; // 指向 int* 的指標
int**& d = c; // int** 指標的參考
```
### 指標與陣列
```cpp=
int b[3] = { 0, 1, 2 }; // 宣告一維陣列
int* a = b; // 指向陣列的指標
int* c = &b[0]; // 指向 b[0] 的指標
// 二維陣列
int d[2][3] = { {4, 5, 9}, {1, 2, 10} };
int* e = d[0];
int* f = &d[0][0];
int* g[2] = { d[0], d[1] };
int** h = g;
int i = h[0][2]; // it's 9.
```
## 參考(Reference)
參考是 C++ 才有的功能,可以簡單看做別名(Alias)的意思。
```cpp=
int n = 10; // 宣告變數
int* p = &n; // 宣告指標
int& r = n; // 定義參考,變數 n 的別名
```
參考不會複製該物件(記憶體區塊),缺點是參考不可以是 NULL、必須要有初始值,且不能參考右值(rvalue)。這邊的 `&` 並不是取址運算元哦!稱之為參考運算元(reference operator)
> 參考與指標最大的不同在於,用在函數當參數使用時,指標實際上依舊是 Call by Value,而真正的 Call by Reference 是 C++ 的參考才具有的。
```cpp=
#include <iostream>
void magic(int a, int b) {
std::cout << "Call by value" << std::endl;
std::cout << "The Value of a in magic: " << a << std::endl;
std::cout << "The Address of a in magic: " << &a << std::endl;
std::cout << "The Value of b in magic: " << b << std::endl;
std::cout << "The Address of b in magic: " << &b << std::endl;
}
void magic2(int* a, int* b) {
std::cout << "Call by pointer" << std::endl;
std::cout << "The Value of a in magic: " << *a << std::endl;
std::cout << "The Address of a in magic: " << a << std::endl;
std::cout << "The Value of b in magic: " << *b << std::endl;
std::cout << "The Address of b in magic: " << b << std::endl;
std::cout << "The address of pointer a: " << &a << std::endl;
std::cout << "The address of pointer b: " << &b << std::endl;
}
void magic3(int& a, int& b) {
std::cout << "Refernce" << std::endl;
std::cout << "The Value of a in magic: " << a << std::endl;
std::cout << "The Address of a in magic: " << &a << std::endl;
std::cout << "The Value of b in magic: " << b << std::endl;
std::cout << "The Address of b in magic: " << &b << std::endl;
}
int main(int argc, char** argv) {
int a = 5;
int b = 6;
int* pa = &a;
int* pb = &b;
std::cout << "In Main Program" << std::endl;
std::cout << "The Value of a in magic: " << a << std::endl;
std::cout << "The Address of a in magic: " << &a << std::endl;
std::cout << "The Value of b in magic: " << b << std::endl;
std::cout << "The Address of b in magic: " << &b << std::endl;
std::cout << "The address of pointer pa: " << &pa << std::endl;
std::cout << "The address of pointer pb: " << &pb << std::endl;
magic(a, b);
magic2(pa, pb);
magic3(a, b);
return 0;
}
```
透過以上程式會發現,在 `main()` 當中的指標 `pa` 與 `pb` 與函數 `magic2()` 當中的指標 `a` 和 `b` ,兩邊的指標記憶體是不相同的,也就是說如果在函數 `magic2()` 修改了指標 `a` 和 `b` 的值(記憶體位置),在 `main()` 中的指標 `pa` 與 `pb` 並不會跟著連動。
參考也可以參照指標,語法如下:
```cpp=
int a = 5; // 一般變數
int &b = a; // a 的參考(a的別名)
int* p = &a; // 宣告指標
int*& r = p; // int* 指標的參考
int&* g = p; // error: cannot declare pointer to 'int&'
```
> 要怎麼理解 `int*&`,從右往左讀就對了,所以它是一個 "參考",參考什麼呢?是整數指標 `int*`;然後需要特別注意一下 `int&*` 是不合法的。
## Template
https://vinesmsuic.github.io/2020/01/12/c++-template/#template-specialization
https://docs.microsoft.com/zh-tw/cpp/cpp/templates-cpp?view=msvc-170
https://hackmd.io/@butastur/cpp11-templates-1
https://www.rocksaying.tw/archives/3641717.html
https://magicjackting.pixnet.net/blog/post/221968938
###### tags: `C++`