changed 4 years ago
Linked with GitHub

指標 & 參照

2021/11/05 電算社第七堂社課


記憶體


是電腦儲存變數值的地方,
可以把它想像成是一個很長的紙帶
上面有很多連續的格子,每一個格子有連續的編號

每個格子是 1 bit(0 or 1)
8 個 bit 組成 1 byte


指標 Pointer


指標是一種變數,
裡面存放一個變數的第一個記憶體位置(address)
可以視為它是"指向該變數的變數"


宣告

int *ptr;

指向(賦值)

int a = 100; int *ptr = &a; //宣告一個指標ptr,指向 a 的記憶體位置 //&是取址的意思,也就是取得a的記憶體位址
//或者是 int *ptr; int b = 100; ptr = &b; //宣告一個指標ptr,指向 b 的記憶體位置

取值

int a = 100; int *ptr = &a; cout << ptr << " 、 " << *ptr << endl; //*ptr可以知道ptr指向的變數的值 //輸出結果 : a的記憶體位置 、 100

改值

int a = 100; int *ptr = &a; cout << ptr << " 、 " << *ptr << endl; //輸出結果 : a的記憶體位置 、 100 *ptr = 110; //它會直接更動指向的變數(a)的值 cout << ptr << " 、 " << *ptr << endl; //輸出結果 : a的記憶體位置 、 110

小差異(常用錯!!)

int a = 10, b = 20; int *ptr = &a; //ptr這個指標指向a ptr = &b; //現在改成指向b *ptr = a; //這個跟上一行不一樣,ptr仍舊指向b,但是b的值被改為與a相同

reference(參照)


reference可以理解成是一個變數的別名
它不像指標會儲存記憶體位置
他反而可以直接操控該變數


int a = 10; int &b = a; //宣告一個reference b,指向a,想像它是a的綽號

應用

int a = 10; int &b = a; cout << a << ' ' << b << endl; //輸出 10 10 b = 100; //會間接讓a也變成100 cout << a << ' ' << b << endl; //輸出 100 100

指標 vs 參照


直接看例子吧:D


#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就是傳值的意思,
呼叫變數時是複製一份數值,
而非將記憶體連動過去
上一堂課中的那些引數都是 call by value


Example:

#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的值

那如果想改變值的話該怎麼辦呢
這時候就必須回傳


#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:

#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:

#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


常見錯誤

#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)

#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)

#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; }
Select a repo