new 一定要與 delete 配合使用嗎?
new和delete
我們在程式設計時一般要new和delete配合使用,否則會引起記憶體洩露,請看下面這個程式:
- #include <iostream>
- #include <windows.h>
- using namespace std;
- void fun1(int *&p)
- {
- int i = 10;
- p = &i;
- cout<<i<<" "<<&i<<endl;
- }
- int main()
- {
-
int *p = new
- cout<<*p<<" "<<p<<endl;
- fun1(p);
- cout<<*p<<" "<<p<<endl;
- Sleep(1000);
- cout<<*p<<" "<<p<<endl;
- //delete p;
- return 0;
- }
執行結果如下:
0 003B33A0
10 0012FE6C
10 0012FE6C
1000 0012FE6C
首先分析一下上面程式的結果,在new了一個int型別的資料後,返回地址給p。(由於new int後面有一個括號,表示初始化內容為0,所以*p為0,p為003B33A0)
然後呼叫func1,形參為實參的引用,所以其實就是p。將p指向i以後,即將p的值修改為i的地址,而*p即為i。所以第二行和第三行輸出結果一樣,到此為止比較容易理解。
最後問題出來了,在sleep(1000)以後,為什麼p的值發生修改了呢?
其實原因是在func1中i是區域性變數,在func1執行完畢後,i需要釋放,那麼釋放到底是什麼意思呢?
其實釋放就是將變數i對應的內容銷燬,標記為未使用狀態,那麼以後程式可以繼續使用這塊記憶體。既然i的內容已經銷燬,那麼*p的內容也變為不可知的狀態,所以在sleep(1000)以後,系統已經將i釋放,此刻p依然指向i,但i的內容已經變為不可知狀態,在程式中變為1000。而在剛執行完fun1(p)的時候系統還未來得及釋放i,所以依然保持10。
好了,問題又來了,注意我在最後把delete p給註釋掉了,肯定有人會以為這樣會造成記憶體洩露,其實當初我也是這麼認為的,當把delete p加上以後,程式在執行到最後,會出現一個警告。
想來想去,其實此時已經完全沒有必要delete了,因為系統釋放i的時候相當於已經執行了delete p的操作,因為i的內容被釋放,而p又指向i,當然p也同時被釋放。
這時候又有疑問了,既然p已經在func1之後完畢後被釋放了,那最後為什麼還能輸出p和*p呢?
因為delete p的操作,其實就是將*p的內容銷燬,p的值依然保持不變,所以依然可以在delete p以後使用p。
不信的話可以將上述程式稍微修改一下:
- #include <iostream>
- #include <windows.h>
- using namespace std;
- void fun1(int *&p)
- {
- int i = 10;
- p = &i;
- cout<<i<<" "<<&i<<endl;
- }
- int main()
- {
- int *p = new int();
- cout<<*p<<" "<<p<<endl;
- //fun1(p);
- cout<<*p<<" "<<p<<endl;
- Sleep(1000);
- delete p;
- cout<<*p<<" "<<p<<endl;
- return 0;
- }
執行結果如下:
0 003B33A0
0 003B33A0
-572662307 003B33A0
可見,在delete p執行以後,p的值並沒有發生變化,只是p所指向的內容被銷燬,變為不可知狀態。
最後,總結一下,new操作一定要配合一個delete操作,但delete不一定是顯式的呼叫,可以由系統幫助完成。而delete p其實只是銷燬內容,即*p,而p本身的值卻並沒有發生變化。