參數策略ios
若是函數的參數是一個指針,不要期望用該指針去動態申請內存。以下:數組
void GetMemory(char *p, int num) { p = (char *)malloc(sizeof(char) * num); } void Test(void) { char *str = NULL; GetMemory(str, 100); //str仍未NULL strcpy(str, "hello"); //運行錯誤 }
緣由是編譯器老是爲每一個參數製做臨時副本。指針參數p, 其副本爲_p,使_p=p。若是改變了_p所指的內容,相應的p所指的內容也跟着改變(畢竟指向一樣的地方)。可是在GetMemory中動態分配內存空間,改變了_p的內容。在調用函數中的p仍是指向NULL。再者,由於函數GetMemory中動態分配了空間,可是沒釋放,這樣調用一次函數,就泄露了一次內存。圖示:
函數
若是非得用指針參數申請內存,能夠用指針的指針做爲參數申請內存spa
void GetMemory(char **p, int num) { *p = (char *)malloc(sizeof(char) * num); } void Test(void) { char *str = NULL; GetMemory(&str, 100); //記得加地址符
strcpy(str, "hello");
free(str) }
原理是同樣的,比較難理解,圖示表示:
指針
比較好的方法是傳指針的引用code
#include <iostream> #include <string> #include <cstring> #include <cstdlib> using namespace std; void GetMemory(char *&p, int num) { p = (char *)malloc(sizeof(char) * num); } void Test(void) { char *str = NULL; GetMemory(str, 100); strcpy(str, "hello"); cout << str << endl; free(str); } int main() { Test(); }
這裏注意指針的引用 爲char* &a,要是很差理解能夠這樣:blog
typedef char* pchar; pchar &a
返回值策略內存
能夠用函數返回值來傳遞動態內存。這中方法比「指針的指針」簡單多了編譯器
char *GetMemory(int num) { char *p = (char *)malloc(sizeof(char) * num); return p; } void Test(void) { char *str = NULL; str = GetMemory(100); //str指向了動態分配的空間 strcpy(str, "hello"); free(str) }
在使用返回值時,千萬別返回指向「棧內存」的指針、引用,由於該內存在函數結束時自動消亡了,返回的指針是個野指針了。例如string
char *GetString() { char p[] = "hello world"; //數組內容存儲在棧區,函數結束時,會釋放掉 return p; } void Test(void) { char *str = NULL; str = GetString(); //由於非配的內存早已釋放掉,此時的str是個野指針,內容是垃圾 cout << str << endl; }
在函數中不定義數組,定義指針,示例:
char *GetString() { char *p = "hello world"; //數組內容存儲在靜態區,函數結束時,不會釋放掉 return p; } void Test(void) { char *str = NULL; str = GetString(); cout << str << endl; }
此時的程序是正確的,可是有一點,此時分配的內存處於靜態區,是隻能夠讀取可是不能夠修改的。