---
# System prepended metadata

title: Pointer
tags: [' note', books]

---

---
tags: books, note
---



# Pointer


## Intro
指標(Pointer)其實也是"**變數**" 只不過比較特殊
指標變數不像其他學過的變數一樣(int / float...) 存取的資料很直觀

```cpp
int a = 48763;
cout << a; //output : 48763
```

而是比較抽象的"**記憶體位址(address)**"

> 紫大 9-2
> ---
> 在我們宣告一個變數的時候
> 編譯器便會配置一塊足夠儲存這個變數的記憶體給它
> 每個記憶體空間都有獨一無二的編號
> 這些編號稱為記憶體的位址(address)
---
Example : 
```cpp
int *ptr = &a;
cout << &a; // output : 0x61fe14
cout << *ptr; // output : 48763
cout << ptr; // output : 0x61fe14
cout << &ptr; // output : 0x61fe08
```
![](https://i.imgur.com/G4EiYfa.png)

---

你可能會想說指標感覺很無用處
但是在之後**實作資料結構時是相當重要的基礎**
而且也更能了解程式的運作
還可以寫出比較彈性的Code


## 宣告指標變數
> 紫大 9-6
```
資料型態 *指標變數
```
Example : 
```cpp
int *ptr;
int* ptr2; //這樣也可以 而且比較清楚是 int* 型態
```

但是

```cpp
int* ptr, ptr2;
```
ptr會是 `int*` 型態沒錯
ptr2卻只會是 `int` 型態

因此
```cpp
int* ptr; //適合用在只宣告一個指標變數
int *left, *right; //適合用在宣告多個
```

## 位址運算子「&」, 依址取值運算子「*」

知道如何宣告指標變數後
現在要做的就是存取變數的位址
用以下範例來解釋
```cpp
int a = 48763;
int *ptr = &a; // 宣告一個ptr指標變數 並使他指向變數a的位址
cout << &a; // output : 0x61fe14 變數a的位址
cout << *ptr; // output : 48763 依指標變數所存取的位址來取值 也就是a
cout << ptr; // output : 0x61fe14 指標變數ptr所存的位址 也就是 &a
cout << &ptr; // output : 0x61fe08 指標變數ptr的位址
```
![](https://i.imgur.com/G4EiYfa.png)

## 動態記憶體配置 new, delete

前面已經提到說指標是拿來指向記憶體位置
那假如你未設立他初始指向的位址
```cpp
int *ptr;
```
他有可能就會亂指向其他記憶體位址
如果這時你再對ptr進行操作
```cpp
*ptr = 48763;
```
就會出現不可預期之錯誤
~~(電腦應該是不會這樣就爛了啦)~~

---

所以為了保險起見
一般我們在宣告指標時都會像這樣
```cpp
int *ptr = NULL;
int *ptr = 0;
int *ptr = nullptr; // C++11
```
在還沒要使用到指標的時候
把他指向空指標
這樣就不會爛了

---

而指標最常用到的地方
就是進行記憶體的配置
因為平時在打Code的時候 資料不一定會是固定的數量
這時就需要動態的來配置記憶體 方便進行操作

像是在使用陣列時
```cpp
int arr[MAXN];
```
如果沒告訴你MAXN的範圍
你要存多少資料你也不會知道
這時動態記憶體配置就派上用場了

最基本的語法是像這樣
new : 
```cpp
資料型態 指標名稱 = nullptr;
指標名稱 = new 資料型態(建構元); // 資料型態要一樣
```
[建構元](https://hackmd.io/@konchin/book/%2FXToC9yD-R6Oxo7-G8nMy6Q#Constructor)的解釋

delete:
```cpp
delete 指標名稱;
```

大概懂這個概念後
可以繼續搭配[類別](https://hackmd.io/@konchin/book/%2FXToC9yD-R6Oxo7-G8nMy6Q#Class)來開始實作一些簡單的資料結構
方便熟悉用法

## 小結

以上就是指標的初步認識
實際上真的沒有那麼困難
只不過平時打Code用不到 所以覺得有點玄而已
接下來要介紹參照(Reference)

# Reference

## Intro

平常會用到參照的時機
大部分都是在寫函數的時候
我們一開始學函數的時候 應該都知道
```cpp
void change_value(int a)
{
    a = 10;
    return;
}
int main()
{
    int value = 20;
    change_value(value);
    cout << value; //output : 20
}
```

這是因為我們所傳遞引數的方式是「傳值呼叫」(call by value)
編譯器會將欲傳入函數的引數值另外複製一份 供函數使用
所以不管怎麼在函數改變值 都不會影響原先變數的值

---

> 紫大 7-4
> ---
> 「參照」(reference)就像是變數的暱稱或別名
> 他可以代替某個變數
> 也就是說 當一個變數有了他的參照之後
> 在程式中使用參照的名稱 即可直接存取這個變數

---

所以如果我們是傳遞參照(pass by reference)的話
就可以直接修改原變數的值
```cpp
void change_value(int &a)
{
    a = 10;
    return;
}
int main()
{
    int value = 20;
    change_value(value);
    cout << value; //output : 10
}
```

你可能會有點搞混說
阿e04 前面Pointer不是說`&`是取位址嗎
現在開始解釋了喔喔喔

## 宣告參照

```
資料型態 變數名稱;
資料型態 &參照名稱 = 變數名稱; // 資料型態& 參照名稱 = 變數名稱; 亦可
```

注意到了嗎 這跟指標大大不同

```
指標的型態是 資料型態*
參照的型態是 資料型態&
```

Example :
```cpp
int a = 10;
int* ptr = &a;
int& ref = a;
ref = 48763;
cout << a; // output : 48763
cout << *ptr; //output : 48763
```

## 小結

參照就這樣子而已了

# Others

## 再用指標指向指標?

你可能會想說
阿那 指標能不能再指向指標 參照是不是還可以參照(verb)參照
是可以沒錯
前者比較有意義 後者因為都一樣 所以那麼多參照是要幹啥呢
```cpp
int a = 48763;
int *ptr = &a;
// int *ptr = &ptr; // wrong 因為你要指向一個指標 所以型態應該要是 int**
int **ptr2 = &ptr; // right
```

## 陣列

你一定試過
```cpp
int arr[5] = {4, 8, 7, 6, 3};
cout << arr; // output : 0x61fe00
```
為甚麼不是輸出 4 8 7 6 3 呢
詳情請看 **紫大 9-30**


> [name=9th教學顧問][time=Sat, May 20, 2020 1:37 PM]
