先來看一段代碼:
void GetMemory(char *p) { p = new char[20]; } void Test() { char * str = NULL; GetMemory(str); strcpy(str,"hello,world"); delete str; str = NULL; }
(1) 會造成內存洩漏
(2) 在strcpy會出現程序奔潰。
以下是具體的問題分析:
我們知道函數一般都是傳值,即使是指針的值,也是一個數值而已。下面通過調試來看看str的值的變化:
第1步剛剛進入Test函數,str分配好地址0x0012f464,但是裡面的值為0xcccccccc,即為沒有初始化的值;
<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PGJyPgo8L3A+CjxwPjxicj4KPC9wPgo8cD48aW1nIHNyYz0="http://www.2cto.com/uploadfile/Collfiles/20140128/20140128095624125.jpg" alt="\">
第2步在Test函數中,str被賦值為NULL即,此時str的地址0x0012f464,但是裡面的值為0x00000000,注意因為此時沒有進入子函數GetMemory,所以p還沒有分配內存;
第3步進入子函數GetMemory中,str的值被傳遞給新申請的p。此時p的地址0x0012f384,但是裡面的值為0x00000000;
第4步在子函數GetMemory中,在堆上申請的 new char[20]返回的地址值保存在p中。此時p的值已經由之前的0x0012f384變為0x0035cf08;
第5步在跳出子函數GetMemory,返回到Test函數中,注意觀察此時的變量狀態:臨時變量p的生命周期隨著子函數GetMemory的結束一起結束了,並沒有把新申請的new
char[20]的地址傳遞到Test函數中來;str的值還是之前的,沒有做任何改變。
通過上面的一系列調試截圖,我們知道函數傳遞時僅僅是傳遞的值。借用一位網友的總結:
“函數的參數進行值拷貝,即使傳的是指針,也的對指針(即指針裡存的地址)的拷貝。”
遇到搞不清楚的時候勤動手,多調試,肯定會搞明白的。
可能聰明的你還想追問,那指針做函數參數是怎麼用的呢?
其實我們之所以使用指針,僅僅是因為通過它作為紐帶可以找到我們想操作的東西,大多數時候都是通過*p="N';或者p[0]='N';或者*(p++)='N';之類用法來修改指針指向的地址裡面的變量值,而不是修改指針的值。更多的知識請讀者自己在使用中慢慢去體會了。
參考網址列表:
http://www.cppblog.com/mzty/archive/2006/07/07/9531.html
http://www.cnblogs.com/nerohwang/p/3481725.html