寫在開頭
在最近學習編程時,總是會思考一些細枝末節(jié)的問題,這些問題總是會擾亂我的心緒,可能是由于之前沒有認真的探究,或者是曾經探究過,但是已經忘掉了,今天一直在腦海里思考的問題是,為什么有的時候需要用new來創(chuàng)建一個對象或數(shù)組或結構體呢?當然,不同的老師可能針對這個問題已經提過不止一次了,但是親身實踐才發(fā)現(xiàn),這些細節(jié)也足夠讓人糾結,所以今天就把學到的內容進行一個總結,以備不時之需。
-
堆與棧的概念
同意堆與棧的區(qū)別中對不同場景下的堆棧定義區(qū)別:
(1)程序內存布局場景下,堆與棧表示的是兩種內存管理方式;
(2)數(shù)據(jù)結構場景下,堆與棧表示兩種常用的數(shù)據(jù)結構。
-
堆與棧的定義
在編程初期,我們一直都在與棧打交道,從計算導論與程序設計這門課開始,就已經開始接觸棧這一概念了,那么棧最基礎的知識就不再多提了,需要強調的是棧在物理上的地址空間是連續(xù)的,而且后申請的變量具有更小的地址值,而且棧中的數(shù)據(jù)生命周期與函數(shù)相同,函數(shù)調用結束了,棧也就隨之刪除。
但是堆有與棧不相同的內涵,在堆上的數(shù)據(jù)地址與申請的順序沒有嚴格的匹配關系,是隨機申請的空間,只要不主動釋放堆的數(shù)據(jù),就會一直存在,所以如果大量申請堆中數(shù)據(jù)并且沒有釋放,就會出現(xiàn)內存泄漏的問題。但是釋放堆的內存也要注意,應該對所要釋放的指針進行判空操作,值得注意的是,老師課上曾強調過在delete指針前,要判斷指針是否為空,但是查閱資料后發(fā)現(xiàn)好像并不需要這么做,因為g++中會自動判斷要釋放的指針是否為空,總結來說就是,可以判斷,但沒必要。但是為了避免釋放的指針成為野指針,要把指針賦為NULL。 -
堆與棧的區(qū)別
其實說了不少,堆與棧的區(qū)別在上面就已經體現(xiàn)出來了。總結來說就是,在需要開辟大量內存空間或者希望控制數(shù)據(jù)的生存周期時,就應該通過堆,這也是在接下來的數(shù)據(jù)結構聯(lián)系中需要注意的細節(jié)。
下面是以前曾經用過的動態(tài)申請二維數(shù)組的方法作為范例:
//動態(tài)申請一個m行n列的整形數(shù)組
int **p = new int *[m];
for(int i = 0;i < m; ++i)
p[i] = new int[n];
//內存釋放
for(i = 0;i < m; ++i)
delete[] p[i];
delete[] p;
事實上,使用C++的STL中vector可以更加方便的完成二維數(shù)組的動態(tài)申請:
//注意int后面的> >之間要有空格,否則會認為是重載的">>"
vector <vector<int> > p(m,vector<int>(n));