2013年9月29日 星期日

C++指標與動態記憶體

把之前看得 C++ 教學,有關指標與動態記憶體的部份整理一下


配置動態記憶體
C++ 可以用 new 配置一塊動態記憶體,讓指標直接指到這塊記憶體。
int * ptr;
// 分配一塊動態記憶體,大小為 int,ptr 指到此記憶體位址
ptr = new int; 
int * ptr;
// 分配一塊動態記憶體,大小為 int,內容初始化為80,ptr 指到此記憶體位址
ptr = new int(80);


動態記體體管理(不是靜態記憶體)
靜態記憶體 => 編譯時即決定記憶體大小。例如 int x;
動態記憶體 => 使用 Heap (也叫 freestore),可能會滿,所以可能會配置失敗。
判斷是否配置失敗
int* p;
p = new int;
if(p==NULL){
   // 配置記憶體失敗
}
註:這邊提到 Heap 也叫 freestore,但好奇的我,還是 google 了一下,看是否有差異。
C++, Free-Store vs Heap
Heap or Free-Store?
free store 和 heap
What is the difference between the heap and the free store

動態配置的記憶體需要自己管理,不會自己消失,要用 delete 回收
int *p = new int(20);
// delete p 是回收動態配置出來的 new int(20),
// 不是回收 p,p 仍然指在 new int(20) 原本的記憶體位址,p 是由系統自動管理
delete p; 

// 若 new int(20) 已回收,再使用 *p ,可能得到不可預期的結果
printf("*p = %d \n", *p); 
// 所以較好的習慣,delete 後,也將指標設為 NULL
int *p = new int(20);
delete p;
p = NULL; // new int(20) 回收後,將 p 設為 NULL


自動變數 & 動態變數
local 變數(自動變數) => functoin 產生時自動產生,function結束時自動回收。
dynamic 變數(動態變數) => 程式執行過程中才使用 new 產生,最後用 delete 回收,compile 時不分配記憶體。



動態一維陣列
int* p;
p = new int[10]; // 配置
delete [] p; // 回收
p = NULL;


動態配置多維陣列
範例:
typedef int* IntArrPtr;
IntArrPtr* m = new IntArrPtr[3]; // 同 int** m = new IntArrPtr[3];
for(int i = 0; i<3; i++)
{
    m[i] = new int[4];
}
=>3x4 動態陣列
=>m[0] 裡面的元素是連續的、 m[1] 裡面的元素是連續的、 m[2] 裡面的元素是連續的
=>但 m[0]、m[1]、m[2] 之間不是連續的


動態配置二維陣列方法1:
int* m[3];
for(int i = 0; i<3; i++)
{
    m[i] = new int[4];
}


動態配置二維陣列方法2:
int** m;
m = new int*[3];
for(int i = 0; i<3; i++)
{
    m[i] = new int[6];
}


delete 動態多維陣列
多維的動態陣列,回收時(deallocate),要反向回收。
範例:
// 產生多維動態陣列
int** m;
m = new int*[3];
for(int i = 0; i<3; i++)
{
    m[i] = new int[6];
}

// 回收多維動態陣列
for(int i = 0; i<3; i++)
{
    delete m[i];
}
delete[] m;
m = NULL;


陣列複製
shallow copy(淺層複製):copy by address
int *a, *b;
a = new int[3];
b = a; //淺層複製
Deep copy(深層複製):copy by value
int *a, *b;
a = new int[3];
b = new int[3];
for(int i=0 ; i<3; i++)
{
    b[i] = a[i]; //深層複製
}


用指標當函式參數
void aa(int x, int y); // => aa(num1,  num2); // pass by value
void aa(int &x, int &y); // => aa(num1,  num2); // pass by reference
void aa(int *x, int *y); // => aa(&num1,  &num2); // pass by pointer


pass array by function
把 array 傳到 function 裡面
int aa(int* arrPtr, in num)
{
}
int aa(int arr[], int num)
{
}


function 回傳 array
int [] aa(); // 不合法的寫法
int * aa(); // 合法,但只能傳回一個 array 的記憶體位址


動態分配 C-String
char * w[3];

char * str1 = new char[6];
strcpy(str1, "test1");
w[0] = str1;

char * str2 = new char[7];
strcpy(str2, "test22");
w[1] = str2;

char * str3 = new char[8];
strcpy(str3, "test333");
w[2] = str3;


沒有留言:

張貼留言