66
Chapter 12 Pointers and Dynamic Arrays

Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

  • View
    230

  • Download
    4

Embed Size (px)

Citation preview

Page 1: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Chapter 12

Pointers and Dynamic Arrays

Page 2: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2

Overview

• Pointers (12.1)• Dynamic Arrays (12.2)• Classes and Dynamic Arrays(12.3)

Page 3: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 3

12.1Pointers ( 指標 )

• 指標的內容是變數的記憶體地址 • 記憶體地址可拿來當做變數的名稱

• 假如一個變數需要 3 個記憶體空間 ( 一般是以 byte 為單位 ), 則第 1 個記憶體空間的地址可當作該變數的名稱

• 當一個變數被用來當作 call-by-reference 的參數時 , 其實就是傳遞其記憶體地址

Page 4: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 4

Pointers Tell Where To Find A Variable

• 指標就是用來告訴程式設計師某個變數在記憶體的地址

• 指標透過地址告訴程式設計師一個變數儲放在哪裡,所以說指標 指向 (“point” to) 一個變數

Page 5: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 5

Declaring Pointers

• 指標變數必須宣告成含有 * • Example: 下例宣告指向一個 double 變數的指

標 :

double *p;

• ‘*’ 標示變數 p 是一個指標

Page 6: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 6

Multiple Pointer Declarations

• 要在一個宣告中宣告多個指標,在每個指標前加上 ‘ *’• Example:

int *p1, *p2, v1, v2;

p1 and p2 指向 type int 的變數v1 and v2 是 type int 的變數

Page 7: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 7

The address of Operator

• ‘&’ 運算子可用來得到某變數之記憶體地址,該結果可以給指向該變數資料型態的指標

• Example: p1 = &v1;

執行後, p1 指向 v1 v1 也可以被稱為 “ p1 指過去的變數 "

Page 8: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 8

The Dereferencing Operator ( 提領:去除記憶體地址 )

• C++ 使用 ‘ *’ 運算子處理指標的另一個做法 • “p 指過去的變數” 在 C++ 中可以用 *p 表示

• ‘*’ 在這種狀況就是 提領 (dereferencing) 運算子• p 在這種狀況就是被提領了 (dereferenced)

Page 9: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 9

這列執行後, v1 及 *p1 為相同變數

A Pointer Example

• v1 = 0;p1 = &v1;*p1 = 42;cout << v1 << endl;cout << *p1 << endl;

輸出 : 42 42

Page 10: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 10

Pointer Assignment

• 指定運算子 ( = ) 可用在指標上• Example: 如果 p1 指向 v1 ,則

p2 = p1;

會使 *p2, *p1, 及 v1 都是同一變數的不同名稱

Page 11: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 11

Display 12.1

Caution! Pointer Assignments

• 使用指標變數來進行指定 (assignment) 時要特別注意以下的不同

• p1= p3; // 改變 p1 指向之記憶體地址

• *p1 = *p3; // 改變 p1 指向之記憶體地址裡的值

Page 12: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 12

The new Operator

• 使用指標時 , 即使沒有變數名稱也能改變該指標指向之記憶體裡的值• 下例新增一個指向整數 (int) 之無名變數的指標 :

p1 = new int;• 這個變數可以用 *p1 來處理 ( 存取其值 ) • *p1 可用於任何 integer 變數可以出現的地方

cin >> *p1; *p1 = *p1 + 7;

Page 13: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 13

• 使用 new 運算子產生的變數叫做 動態變數 (dynamic variables)• 動態變數 在程式執行時才會被新增其記憶體空間 或 送

回給作業系統• Display 12.2 有 pointers and dynamic

variables 更多範例

Display 12.2 程式碼的解說在 Display 12.2

Display 12.3

Dynamic Variables

Page 14: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 14

new and Class Types

• new 運算子用於類別 (class) 資料型態時會呼叫建構子 (constructor) 並配置記憶體給該物件

• 如果 MyType 是一個類別 class 資料型態 , 則

MyType *myPtr; // 產生指向一個 MyType 物件 // 的指標

myPtr = new MyType; // 呼叫 MyType 預設建構子 myPtr = new MyType (32.0, 17); // 呼叫 Mytype(double, int) 建構子

Page 15: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 15

Basic Memory Management

• 記憶體中有一塊區域叫做自由儲存區 ( the freestore ) ,表示尚未配置給任何變數的記憶體區域,預留給在程式執行時所新增的動態變數• 新增的動態變數會使用 freestore 的記憶體• 如果 freestore 全部被用光了 , new 的呼叫就會失敗

• 不再需要的動態變數所佔用之記憶體可以回收至 freestore• 當程式不再使用一個變數時 , 該變數可被 delete 掉,

該變數所使用的記憶體就會回到 freestore

Page 16: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 16

The delete Operator

• 當程式不再需要一個變數時 , 可以刪除 (delete) 他 以將記憶體回收至 freestore• Example:

delete p;

執行後, p 的值 ( 記憶體地址 ) 就是未定義 (undefined) ,且原來 p 所指向之記憶體就回收至 freestore

Page 17: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 17

Dangling Pointers

• 使用 delete 於一指標變數 摧毀掉該變數所指向之動態變數

• 如有另一指標變數指向該動態變數 , 則該指標變數也會變成未定義 (undefined)

• 未定義之指標變數也叫做 dangling pointers ( 晃蕩指標 ) • 提領 (dereference) 一個 dangling pointer (*p) 通常會

使程式當掉

Page 18: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 18

Automatic Variables

• 函式中宣告的變數所需的記憶體空間,通常在執行到該函式時會被新增,當程式離開該函式時,該函式所新增的記憶體空間會被回收• 這些可稱為自動變數, 因為他們的新增與回收是由執行

程式自動控制• 程式設計師必須運用 new 及 delete 手動控制指

標變數的新增及回收

Page 19: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 19

Global Variables

• 在所有函式外面宣告之變數被稱為全域變數• 全域變數可在程式任何地方使用 ( 包括在函式內 )• 全域變數一般很少用

Page 20: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 20

Type Definitions

• 一個名稱可以用來定義新的資料型態 , 該名稱之後就能用來宣告變數

• 關鍵字 typedef 就是用來定義新的資料型態的名稱• 語法 :

typedef Known_Type_Definition New_Type_Name;

• Known_Type_Definition 可以是任何資料型態

Page 21: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 21

Defining Pointer Types

• 為避免使用指標時的錯誤 , 可以定義一個指標資料型態• Example: typedef int* IntPtr;

定義一個新的資料型態 , IntPtr, 給指向 int 變數的指標

• 之後 , 以下兩個宣告有相同意義 IntPtr p;

int *p;

Page 22: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 22

Multiple Declarations Again

• 使用以下的新資料型態 IntPtr : typedef int* IntPtr;

• 可避免宣告兩指標變數時,犯了以下的宣告錯誤 : int *P1, P2; // 只有 P1 是指標變數, P2 不是

// 指標變數• 改用以下宣告 IntPtr P1, P2; // P1 and P2 都是指標變數

Page 23: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 23

Pointer Reference Parameters

• 使用 typedef 的第 2 個好處是在函數的參數定義

• Example: void sample_function(IntPtr& pointer_var);

比下例清楚 void sample_function( int*& pointer_var);

Page 24: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 24

Section 12.1 Conclusion

• Can you• Declare a pointer variable?• Assign a value to a pointer variable?• Use the new operator to create a new variable in the

freestore?• Write a definition for a type called NumberPtr to be

a type for pointers to dynamic variables of type int?• Use the NumberPtr type to declare a pointer variable

called my_point?

Page 25: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 25

12.2Dynamic Arrays

• 動態陣列指陣列的大小必須於程式執行時才知道,無法於程式設計時就知道其大小。

Page 26: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 26

Pointer Variables and Array Variables

• 陣列變數其實就是指向陣列第一個元素的指標變數• Example: int a[10];

typedef int* IntPtr; IntPtr p;

• a and p 為相同種類之變數

• 因為 a 是指向 a[0] 的指標變數 p = a;會使 p 與 a 指向相同的變數 ( a[0] )

Page 27: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 27

Display 12.4

Pointer Variables As Array Variables

• 反方向來說,指標變數也可以當陣列變數來使用

• Example: p[0], p[1], …p[9] 都符合 C++ 的語法

• 變數 a 可以當作指標來使用,但是 a 的指標值 ( 即其記憶體地址 ) 不能被異動

• 以下不符合 C++ 的語法 : IntPtr p2;

… // p2 is assigned a value a = p2 // attempt to change a

Page 28: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 28

Creating Dynamic Arrays

• 一般陣列的大小在程式設計師寫程式時就知道• 但假設程式設計師預估的值太大 ?

• 程式執行時浪費記憶體• 但假設程式設計師預估的值太小 ?

• 某些狀況下,程式可能無法執行

• 動態陣列就是要在程式執行時給程式剛好大小的陣列,不會太大,也不會太小

Page 29: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 29

• 動態陣列是用 new 運算子產生

• Example: 下例產生一個含 10 個 double 元素之動態陣列 : typedef double* DoublePtr; DoublePtr d; d = new double[10];

• 這樣 d 就可以如一般陣列一樣使用 !

這可以是一個 integer 變數 !

Creating Dynamic Arrays

Page 30: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 30

• ( 接上頁 ) d 這個指標變數指向 d[0]• 當程式不再需要這個陣列 , 這個陣列應該要回收至

freestore• Example: delete [ ] d;

• 中括號 [ ] 告訴 C++ 一個動態陣列要被回收刪除了,因此 C++ 會檢查此動態陣列的大小以了解應該要回收多少個元素

• 如果忘了加上 [ ] ,仍然為合法的 C++ 語法,但 C++ 會只回收陣列第 1 個元素

Display 12.5 (1)

Display 12.5 (2)

Dynamic Arrays (cont.)

Page 31: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 31

Pointer Arithmetic

• 陣列所代表的記憶體地址可以執行加減運算• 以 double 動態陣列 , d, 為例 , 再提醒一次 d 指

向 d[0]• 運算式 d+1 為 d[1] 的地址, d+2 為 d[2] 的地址

• 注意加 指標 +1 會讓 指標加上該變數所需之記憶體的大小

Page 32: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 32

Pointer Arithmetic Operations

• 指標的加加減減• ++ and - - 運算子可用於指標• 相同資料型態的兩個變數的指標可以拿來相減,可以得

到這兩個指標間的元素個數• 注意此兩個變數必須在同一陣列

• 下例顯示指標的加減 : for (int i = 0; i < array_size; i++) cout << *(d + i) << “ ” ; // 與 cout << d[i] << “ ” ; 同樣的意思

Page 33: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 33

Multidimensional Dynamic Arrays

• 以下為產生一個 3x4 二維整數動態陣列 ( 相同方法可擴充至更高維動態陣列 ) 的注意事項• 視多維動態陣列 為 以陣列為基底 的陣列• ( 上層 )首先產生一個 “基底為整數指標” 之一維動態陣

列• 先定義 整數指標 的新資料型態 :

typedef int* IntArrayPtr;• 再定義其動態陣列 m:

IntArrayPtr *m = new IntArrayPtr[3];

• (底層 ) 其次,對 m 中的每一個指標 , 產生一個整數的動態陣列

• for (int i = 0; i<3; i++) m[i] = new int[4];

Page 34: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 34

m IntArrayPtr's

int's

IntArrayPtr *

A Multidimensional Dynamic Array

• 上頁的二維動態陣列圖示如下 :

Page 35: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 35

• 刪除多維動態陣列的方法 (先回收底層,再回收上層 )• 每一個呼叫 new 所產生的動態陣列都需要一個對應的

delete[ ] 呼叫• Example: 以下刪除上頁之二維動態陣列 :

for ( i = 0; i < 3; i++) delete [ ] m[i]; //先刪除底層的整數動態陣列 delete [ ] m; // 再刪除 IntArrayPtr 動態陣列

Display 12.6 (1) Display 12.6 (2)

DeletingMultidimensional Arrays

Page 36: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 36

Section 12.2 Conclusion

• Can you• Write a definition for pointer variables that will be

used to point to dynamic arrays? The array elementsare of type char. Call the type CharArray.

• Write code to fill array "entry" with 10 numbers typed at the keyboard? int * entry; entry = new int[10];

Page 37: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 37

12.3Classes and Dynamic Arrays

• 動態陣列的基礎資料型態可以是類別• 如 Watch *p;

X=10;

p = new Watch[x];

• 一個類別可以有 動態陣列的 成員變數• StringVar 就是一個範例 .

Page 38: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 38

Program Example:A String Variable Class

• 我們將定義 StringVar 類別• StringVar 物件是用來代表字串• StringVar 物件使用字元動態陣列,其大小必須在執行

程式時才知道 • StringVar 類別與 11-2 的 string 類別功能相似

Page 39: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 39

The StringVar Constructors

• StringVar 預設建構子 產生一個代表空字串的 StringVar 物件,此字串最大長度設為 100 (註:因為此字串可能變長,因此需預留空間 )

• StringVar 第 2 個建構子需要一個 int 的參數,來決定此空字串物件以後之最大長度值

• StringVar 第 3 個建構子需要一個 C-string的參數以…• 將該 C-string 的長度設為此字串之可能最大長度• 將該 C-string 複製到此字串之內部動態陣列變數上

Page 40: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 40

Display 12.7 (1) Display 12.7 (2)

The StringVar Interface

• 除了建構子 , StringVar 的介面包括 :• 成員函式 :

• int length( );• void input_line(istream& ins);• friend ostream& operator << (ostream& outs,

const StringVar& the_string);

• Copy 建構子 … (晚點再討論 )• Destructor 解構子… (晚點再討論 )

Page 41: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 41

Display 12.8

A StringVar Sample Program

• 使用 StringVar 在 Display 12.7 的介面我們可以寫一使用 StringVar 類別之程式• 此程式內的 conversation 函式可以:

• 產生 2 個 StringVar 物件 , your_name 及 our_name• your_name 的字串最長可達 max_name_size • our_name 初始值為 “ Borg” ,只能改變為不大於

4 個字元的字串

Page 42: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 42

Display 12.9 (1)

Display 12.9 (2)

The StringVar Implementation

• StringVar 使用一個字元動態陣列來存放代表該字串的字元們• StringVar 建構子呼叫 new 為成員變數 value 產生動

態 字元陣列 • value 要用 ‘ \0’ (虛字元 ) 來中止字串 (請參考 11-1)• 此陣列之大小必須等到程式執行 new 時才會知道

• 建構子的參數 ( 不論是 預設建構子、一個整數參數之建構子、一個字串參數之建構子 中任一個 ) 會決定其大小

Page 43: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 43

Dynamic Variables

• 只有呼叫 delete 運算子,動態變數 ( 及陣列 ) 才能回收• 即使一個區域指標變數在函式結束後自動回收 , 該指標

所指向的動態變數 ( 及陣列 ) 會留在程式中,除非呼叫 delete 將其回收

• 但是使用 SringVar 類別的程式設計師不可能知道 StringVar 是用了一動態陣列作為其私有成員變數,所以當程式不再需要一個 StringVar 物件時,不會也不能呼叫 delete 來回收動態陣列

Page 44: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 44

Destructors

• 解構子是一個成員函數,當該類別的物件離開其有效範圍時 ( 如函式結束時、 for 迴圈結束時等等 ) ,解構子會被自動呼叫 • 解構子必須含有將建構子產生的動態陣列回收的程式碼• 一個類別僅需要一個不用任何參數的解構子• 解構子的宣告就是在預設建構子前加上 ~

• Example: ~StringVar( );

Page 45: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 45

~StringVar

• StringVar 的解構子必須呼叫delete [ ] 來回收動態陣列的記憶體空間至自由儲存區 (the freestore)• Example: StringVar::~StringVar( )

{ delete [ ] value; }

Page 46: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 46

Display 12.10 Display 12.11

Pointers as Call-by-Value Parameters

• 在函式呼叫時,將指標 (pointers) 作為 call-by-value 的參數會產生沒有預期到的結果• 記得參數 (parameters) 是函式的區域變數

• 在函式內改變參數 (parameter) 的值,不會造成引數 (argument 即呼叫函式的變數 ) 的值跟著改變

• 參數的值設為引數 (argument) 的值,當引數為指標時其值為一記憶體地址

• 因此參數及引數有相同之值 ( 即指標指向之記憶體之地址 )

• 如果參數用來改變其地址指向之記憶體內容 , 因為引數指向之記憶體即為參數指向之記憶體,因此引數指向之記憶體內容也改變了,如 Display 12.10, 12.11 所示

Page 47: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 47

Copy Constructors

• 如果不想造成上頁的副作用 ( 即用指標變數做引數呼叫 call-by-value 的函式參數,可以改變此指標變數指向的變數的值 ) ,可用 複製 (copy) 建構子幫忙解決

• 複製建構子的參數之資料型態即為該類別• 此參數必須為 call-by-reference• 此參數通常是一個 constant 參數, ( 不改變引數物件

的內容 )• 此建構子產生一個完整且獨立的引數複製物件,讓引數

物件與該新生物件不會糾纏在一起

Page 48: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 48

StringVar Copy Constructor

• StringVar 之複製建構子程式碼如下:• 產生一個新的動態陣列準備來放字串的字元• 將引數的字串 ( 即動態字元陣列 ) 複製到此物件剛產生

的動態字元陣列StringVar::StringVar(const StringVar& string_object)

: max_length(string_object.length() ){ value = new char[max_length+ 1]; strcpy(value, string_object.value);}

Page 49: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 49

Calling a Copy Constructor

• 在宣告該類別的物件時,複製建構子與其他建構子的呼叫方式相同

• 複製建構子在以下狀況會被自動呼叫• 宣告時,當其引數為相同類別的物件• 當一個函式傳回一個該類別的值 ( 即物件 ) • 當一個 call-by-value 參數以該類別的物件作為引數呼

Page 50: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 50

The Need For a Copy Constructor

• 假設沒有複製建構子,下例顯示在引數呼叫時,會有什麼問題• void show_string(StringVar the_string)

{ …}

StringVar greeting("Hello");show_string(greeting);cout << greeting << endl;

• 當呼叫 show_string(greeting) 時 , greeting 被複製到參數 the_string

• the_string.value 被設為與 greeting.value 相同

Page 51: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 51

greeting.value the_string.value

"Hello"

The Need For a Copy Constructor (cont.)

• 因為 greeting.value 及 the_string.value 都是指標 , 他們指向同一動態陣列

Page 52: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 52

greeting.value the_string.value

Undefined

The Need For a Copy Constructor (cont.)

• 當 show_string 執行結束時 , the_string 的解構子會自動被執行 , 將 the_string.value 指向之動態陣列回收至自由儲存區 ( the freestore)

• 這時 greeting.value 指向的記憶體已經被回收至自由儲存區 ( the freestore)

Page 53: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 53

The Need For a Copy Constructor (cont.)

• Greeting 這個 StringVar 物件有 2 個問題• 輸出 greeting.value 很可能會出現錯誤

• 有時 OK ,但不能靠運氣• 當離開 greeting 的有效範圍時 , 他的解構子會自動被呼

叫• 同一記憶體地址被解構子呼叫回收 2 次會造成系統錯誤

(system crashing error)

Page 54: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 54

greeting.value the_string.value

"Hello" "Hello"

Copy Constructor Demonstration

• 當有了複製建構子,上面的問題就不會發生了• greeting.value 及 the_string.value 指向記憶體不同位

Page 55: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 55

greeting.value the_string.value

"Hello" undefined

Copy Constructor Demonstration (cont.)

• 當 the_string 離開有效範圍 ( 即函式結束 ), StringVar 的解構子會被呼叫 , 將 the_string.value 回收至自由儲存區 (the freestore )

• greeting.value 仍然還在,可以被存取、被回收

Page 56: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 56

When To Include a Copy Constructor

• 當一個類別的定義 ( 即實做 ) 需用到指標及 new 來動態配置記憶體 , 就需要複製建構子

• 當一個類別的定義沒有用到指標及 new 來動態配置記憶體 , 就不需要複製建構子

Page 57: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 57

The Big Three

• 大三元包括• 複製建構子• 指定運算元 ( 下頁說明 )• 解構子

• 如果需要定義其中一個 , 三個就都需要定義

Page 58: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 58

The Assignment Operator

• 給定以下宣告 : StringVar string(10), string2(20);這個程式碼 string1 = string2;是合法的語法

• 但是 , 因為 StringVar‘s 的成員變數 value 是一個指標 , 我們會將 string1.value 及 string2.value指向同一記憶體位置• 會使得前面討論複製建構子所提的問題又再重現

Page 59: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 59

Overloading =

• 解決之道就是覆蓋 ( overload ) 指定運算子 ( = ) ,讓 StringVar 的指定不致產生問題• = 運算子是以成員函式 (member function) 來定義• Example: operator = declaration

void operator=(const StringVar& right_side);

• right_side 是 = 運算子右邊的引數

Page 60: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 60

Definition of =

• StringVar 的 = 運算子的實做之一 :void StringVar::operator= (const StringVar& right_side){ int new_length = strlen(right_side.value); if (( new_length) > max_length) new_length = max_length;

for(int i = 0; i < new_length; i++) value[i] = right_side.value[i];

value[new_length] = '\0';}

Page 61: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 61

= Details

• 這個 StringVar = 的版本的作法是• 比較 = 左右兩個 StringVar 物件的長度• 最多只改變左邊 StringVar 物件可允許的最大長度• 會將右邊物件的字串內容複製到左邊物件,而且彼此獨立不會互相影響

Page 62: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 62

Problems with =

• 這個 = 的實做的問題• 通常我們不會去管右邊物件的字串內容大小,我們希望

要一個右邊物件的完整複製品 • 要完成以上要求 , 我們需要先回收左邊物件的動態陣列,然後配置夠大的動態陣列來容納右邊物件的字串內容

• 下頁顯示採用以上方法的一個嘗試,但這是一個有問題 (buggy) 的 = 運算子實做

Page 63: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 63

Another Attempt at =

• void StringVar::operator= (const StringVar& right_side){ delete [ ] value; int new_length = strlen(right_side.value); max_length = new_length;

value = new char[max_length + 1];

for(int i = 0; i < new_length; i++) value[i] = right_side.value[i];

value[new_length] = '\0';}

Page 64: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 64

A New Problem With =

• 上頁的 = 運算子實做的問題• 如果有人無聊到將 = 的左右兩邊設為相同物件的話

my_string = my_string;• 上頁的 = 運算子實做先回收左方物件的動態字元陣列 .• 由於左右兩邊為相同物件 , 右方的動態字元陣列也被回

收了,沒有辦法執行 strlen(right_side.value) ,也無法利用 right_side.value[i] 得到原來的各個字元

Page 65: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 65

A Better = Operator

• void StringVar::operator = (const StringVar& right_side) { int new_length = strlen(right_side.value); if (new_length > max_length) // 只有需要更多空間 { // 時才回收

delete [ ] value; max_length = new_length; value = new char[max_length + 1]; }

for (int I = 0; i< new_length; i++) value[i] = right_side.value[i]; value[new_length] = '\0';}

Page 66: Chapter 12 Pointers and Dynamic Arrays. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Pointers (12.1) Dynamic Arrays

Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 66

Section 12.3 Conclusion

• Can you

• Explain why an overloaded assignment operator is not needed when the only data consist of built-in types?

• Explain what a destructor does?

• Explain when a copy constructor is called?