亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? 13.5 文檔對象數據的銷毀.txt

?? 網上第一本以TXT格式的VC++深入詳解孫鑫的書.全文全以TXT格式,并每一章節都分了目錄,清晰易讀
?? TXT
字號:
13.5 文檔對象數據的銷毀

本章上述內容實現的Graphic程序,還隱含著一個錯誤,當新建→個文檔對象時,或者打開一個文檔
對象時,先前文檔所保存的數據沒有被銷毀,這主要是指 CGraphicView 類OnLButtonUp函數中在堆
上為CGraph對象分配的內存(即下面這條語句調用分配的內存)沒有被釋放。 
CGraph *pGraph~new CGraph(~nDrawType,m-ptOrigin,point); 
當我們新建一個文檔時,程序文檔對象所保存的數據要被銷毀,然后再與一個新的文檔相關聯。然
而對于在堆上分配的內存,必須由程序員自己去釋放。我們可以看一下 CDocument類的 
OnNewDocument函數的實現,其源代碼位于 DOCCORE.CPP中。 
例13-29 

BOOL CDocument::OnNewDocument() 

{ 

if(工sModified())

TRACEO ("Warning: OnNewDocument replaces an unsaved document.\丑 11 ) ; 
DeleteContents() ;  
m_strPathName.Empty();  11  no  path name  yet  
SetModifiedFlag(FALSE);  11  make clean  

return TRUE; 

可以看到, CDocument類OnNewDocument函數的默認實現是調用CDocument類的另一個成員函數 
DeleteContents,以確保這個文檔是空的,然后標記該新文檔是干凈的。同樣的,當單擊【文件\
打開】菜單命令后,程序框架會調用OnOpenDocument函數,其默認實現是打開指定的文件,調用 
DeleteContents函數以確保這個文檔是空的。也就是說,不管是新建文檔,還是打開一個己有文檔,
都是先刪除文檔數據,因為本例是單文檔應用類型的程序,它只有一個文檔對象,該對象將被重復
使用,所以應該在該文檔對象被再次使用之前去刪除和這個文檔對象相關聯的所有數據。因為文件
打開和文件新建都會調用 DeleteContents函數,所以在這個函數中釋放文檔對象在堆上分配的內存
是比較合適的。 DeleteContents畫數是一個虛函數,主要是由框架調用,用來刪除文檔的數據,同
時并不銷
毀CDocument對象本身a它是在文檔將要被銷毀之前被調用,它


使用之前被調用,以確保文檔是空的。對單文檔應用程序來說,這一點特別重要,因為僅僅使用一
個文檔,無論用戶是創建,還是打開另一個文檔,該文檔對象都是被重復使用的。所以在文檔對象
被重復使用之前,應釋放己分配的內存。
對Graphic程序來說,在DeleteContents函數被調用時就應該釋放在堆上分配的CGraph 
創.~ I 519 

第13


這個對象的內存。于是,我們為 CGraphicDoc類增加虛函數: DeleteContents的重載,然后在其中
添加如例 13-30所示代碼。 
1J~ 13-30 

1. void CGraphicDoc::DeleteContents() 

2. { 

3. // TODO: Add your specialized code here and/or call the base class 


4. int nCount i 

5. nCount=m_obArray.GetSize() i 

6. for(int i=Oii<m一obArray.GetSize()ii++) 

7. { 


8. delete m一obArray.GetAt(i) i 
9. m_obArray.RemoveAt(i) i 

10. } 


11. 
12. CDocument::DeleteContents(); 

13. } 


在上述如例 13-30所示代碼中,首先定義了一個整型變量: nCount,保存m_obArray數組中的元素個
數。因為先前利用new操作符分配的內存,所以必須利用delete函數釋放該內存。上述例 13-30所示
代碼中通過for循環遍歷m_obArray數組中的每一個元素,并利用 CObArray類的 GetAt成員函數取出
指定索引的元素。因為在CObArray數組中保存的元素都是指針,所以利用delete函數將刪除這個指
針所指向的堆內存。讀者一定要注意,雖然這時刪除了這個指針所指向的堆內存,但是對于m_obArray
數組所保存的元素來說,其內存并沒有被刪除,也就是說,它所保存的指針值還是存在的,所以我
們需要把數組所保存的元素,即 CGraph指針值刪除掉。 CObArray類中有-個成員函數: RemoveAt,
可以刪除指定索引處的元素,其原型聲明如下所示: 
void RemoveAt( int nlndex, int nCount = 1 )i 
該函數的第一個參數(nIndex)設定索引,第二個參數 (nCount)指定要移走的元素數目。因此,在如
例 13-30所示代碼中,在釋放堆內存之后,就調用RemoveAt函數刪除指定索引i處的元素。
我們在上述例 13-30所示代碼中 for循環處設置一個斷點,調試運行程序,利用相應繪圖菜單命令
繪制一些圖形,例如繪制三條直線,即這時會產生三個圖形對象(/IP CGraph 對象)。我們知道,當
新建文件、打開文件,或者關閉程序時,也就是說,當文檔對象被銷毀時,都會去調用文檔類對象(本
例即CGraphicDoc對象)的DeleteContents函數。因此,我們執行關閉 Graphic程序的操作,程序將
進入上述例 13-30所示的 DeleteContents函數中。讀者將可以看到這時 nCount變量的值等于 3,
這個數值是正確的,因為此時 m_obArray數組中確實是保存了三個元素。然后單步執行程序,這時
索引 i是 0,也就是釋放索引0位置處的元素所在的堆內存(第8行代碼),然后移走元素本身(第9行
代碼),這是第一次循環。繼續運行,進入第二次循環,此時i為1,所以刪除索引為 1的元素所
. 

520 I ~~勢

指向的堆內存(第 8行代碼〉、并移走元素本身(第 9行代碼)。繼續運行,接下來應釋放索引為 2
元素所指的堆內存,但是發現程序直接退出了,并沒有進入第 3次循環。
這里之所有沒有成功刪除內存,主要是因為利用 RemoveAt函數刪除元素時出現了問題,該函數是在
數組指定的索引位置處開始移走一個或多個元素,在這個過程中,它會下移在這個元素之上的所有
元素,并減少這個數組的上界。也就是說. RemoveAt函數的調用會導致數組中剩余元素的重新排列。
例如,數組有三個元素,當移走索引為 O的元素時,原先索引為 1和 2的元素都會下移,即索引 1
的元素現在索引為 O.索引 2的元素現在索引為 1。因此在上述代碼中,第二次進入循環時, i已經
變成 1了,于是它刪除的實際是原先索引為 2的那個元素,即數組中的最后一個元素,但是刪除這
個元素之后,還漏掉了一個元素,即原索引為1,現索引為 O的那個元素。也就說它循環兩次之后就
出現問題了。這是我們經常容易犯的錯誤,把判斷元素數目的代碼放置在條件判斷的位置(上述代碼
中 for循環的條件判斷語句: i< m_obArray.GetSizeO).對于剛才這種寫法,因為刪除元素后,它的
大小就會發生變化. GetSizeO函數的返回值也在不斷變化,原先是 3個元素,移走一個后變成 2個。
所以第三次循環時,索引 i是 2.而 GetSize函數的返回值是1,所以循環結束。而這樣的一種調用,
程序員根本發現不了它有問題。當我們不斷地新建文檔和打開另一個文檔時,實際上就隱含的有內
存泄漏的發生,因為有些對象的內存沒有被釋放。如果我們對 RemoveAt函數調用的機制不太了解的
話,所編寫的代碼就會存在內存泄漏的隱患,因此在這里需要修改代碼,在釋放元素所保存的指針
所指向的堆內存之后(第 8行代碼).先不刪除這個元素本身,然后在 for循環結束之后,也就是所有
元素所指向的堆內存都被刪除之后,再刪除這些元素。為了刪除 m_obArray數組中的所有元素,并
不需要再進行一次循環,逐一刪除,因為 CObArray類中還有一個成員函數: RemoveAll.用于從這個
數組中移除所有元素。也就是說,在上述 for循環之后,可以調用 m_obArray對象的 RemoveAll函
數,刪除其所有元素。這樣的話,程序就不會出現問題了。修改后的代碼如例 13-31所示。 
例 13-31 

void CGraphicDoc::DeleteContents() 
// TODO: Add your specialized code here and/or call the base class int nCount; 
nCount=m一obArray.GetSize(); 
for(int i=O;i<nCount;i++) 
delete m_obArray.GetAt(i); 

//m_obArray.RemoveAt(土) ; 
m_obArray.RemoveAll(); 
CDocument::DeleteContents(); 
m 
這時,讀者可以再次調試運行 Graphic程序,同樣也繪制三條直線,然后執行關閉程

13 

序的操作,程序將進入如例 13-31所示 CGraphicDoc類的 DeleteContents函數中,繼續調試程序,
將會看到 DeleteContents函數中的 for循環確實執行了三次,把程序中分配的堆內存都釋放掉了,
最后移走了數組中的所有元素。
另外,我們還可以采用另一種實現方式,可以從索引最大的元素開始刪除,這時的實現代碼如例 
13-32所示。
例 13-32 

void CGraphicDoc: :DeleteContents() 
{ 
// TODO: Add your specialized code here and/or call the base class 
int nCount; 
nCount=m一obArray.GetSize() ; 
while(nCount--) 
{ 
delete m_obArray.GetAt(nCount); 
m一 obArray.RemoveAt(nCount); 
CDocument: :DeleteContents(); 
在上述例 13-32代碼中,得到數組元素大小后,進行 while循環,在此循環中,刪除當前索引位置
處元素保存的指針所指向的堆內存。當然,這時就可以調用 RemoveAt函數刪除數組索引值最大的那
個元素。我們可以分析一下這時程序的調用流程,首先 nCount等于 3,進入 while循環,先判斷條
件為真,然后 nCount值減 1。于是移走 m_obArray數組中索引為 2的那個元素保存的指針所指向的
堆內存,并刪除元素本身:再進入 while語句,先判斷 nCount值為 2,條件為真,繼續循環, nCount
值減 1變成1,釋放索引 1位置處的元素保存的指針所指向的堆內存,并刪除該元素本身:接下來,
因為 nCount值為1, while語旬的條件仍為真,繼續循環, nCount值減 1變為 0,釋放索引 0位置
處的元素保存的指針所指向的堆內存,并刪除該元素本身:這時,因為 nCount值為 0, while條件
為假,所以 while循環終止。可見,當繪制三條直線時,上述 while循環確實執行了三次。讀者可
以自行調試運行 Graphic程序,測試這段代碼。 


?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产高清无密码一区二区三区| 午夜久久久影院| 91精品在线麻豆| 欧美日韩在线三级| 678五月天丁香亚洲综合网| 色天使色偷偷av一区二区 | 欧美日韩一区二区三区在线| av综合在线播放| 97久久久精品综合88久久| 色综合久久精品| 欧美性色黄大片手机版| 欧美日韩在线精品一区二区三区激情| 欧美三级视频在线观看| 日韩三级视频在线看| 精品国产乱码久久| 国产精品网站在线| 一区二区三区免费观看| 日韩成人伦理电影在线观看| 麻豆精品一区二区三区| 国产激情精品久久久第一区二区| 成人免费观看男女羞羞视频| 色综合天天性综合| 日韩精品电影在线| 久久99深爱久久99精品| 成人av影视在线观看| 91国内精品野花午夜精品| 欧美肥妇毛茸茸| 精品国产1区2区3区| 国产精品视频你懂的| 亚洲国产视频一区二区| 久久国产三级精品| 色综合天天狠狠| 欧美成人a∨高清免费观看| 国产精品丝袜黑色高跟| 天天影视色香欲综合网老头| 国产美女av一区二区三区| 色综合久久久久久久| 欧美电视剧在线观看完整版| 成人欧美一区二区三区白人| 三级在线观看一区二区| av电影天堂一区二区在线观看| 欧美亚洲一区二区在线| 国产亚洲综合在线| 视频一区视频二区中文字幕| av午夜精品一区二区三区| 日韩女优制服丝袜电影| 一区二区三区在线视频免费 | 亚洲欧美自拍偷拍| 日韩av在线发布| 色综合久久中文字幕综合网| 欧美电视剧免费观看| 亚洲国产精品一区二区久久| 福利一区在线观看| 欧美一级视频精品观看| 一区二区在线观看不卡| 大尺度一区二区| 亚洲精品在线免费播放| 男女性色大片免费观看一区二区 | 久久国产尿小便嘘嘘| 欧洲精品一区二区| 亚洲视频免费在线观看| 国产成人精品免费视频网站| 日韩欧美电影在线| 午夜久久福利影院| 欧美午夜不卡视频| 亚洲狠狠丁香婷婷综合久久久| 国产成人精品1024| 久久影视一区二区| 国产一区二区三区四区五区入口| 欧美一区二区成人| 喷水一区二区三区| 制服丝袜亚洲色图| 奇米精品一区二区三区在线观看 | 亚洲aaa精品| 在线观看成人小视频| 亚洲美女淫视频| 91浏览器打开| 91精品国产综合久久精品麻豆| 亚洲激情综合网| 在线精品亚洲一区二区不卡| 一区二区三区国产精品| 色婷婷精品大在线视频| 亚洲综合小说图片| 欧美日韩免费观看一区三区| 亚洲第一会所有码转帖| 7777精品伊人久久久大香线蕉超级流畅| 亚洲最色的网站| 欧美在线啊v一区| 亚洲动漫第一页| 欧美日高清视频| 日韩制服丝袜av| 欧美tk丨vk视频| 国产 日韩 欧美大片| 亚洲欧洲一区二区三区| 在线中文字幕一区二区| 日韩国产欧美视频| 精品国免费一区二区三区| 国产精品77777| 亚洲精品欧美综合四区| 6080日韩午夜伦伦午夜伦| 精品一区二区三区日韩| 亚洲欧洲av在线| 欧美性视频一区二区三区| 美女网站一区二区| 国产精品乱人伦| 欧美久久久久久久久中文字幕| 蜜桃视频在线观看一区二区| 中文字幕国产一区| 欧美三级在线播放| 国产经典欧美精品| 性做久久久久久久免费看| 亚洲精品一区二区三区香蕉| 99re热这里只有精品视频| 首页综合国产亚洲丝袜| 日韩一区在线免费观看| 欧美浪妇xxxx高跟鞋交| 成人h动漫精品一区二区| 午夜精品福利视频网站| 国产亚洲制服色| 欧美卡1卡2卡| 色综合天天综合在线视频| 国产中文字幕一区| 亚洲成人精品一区二区| 中文字幕第一页久久| 日韩免费观看2025年上映的电影| 成人av网站在线观看免费| 美腿丝袜亚洲三区| 亚洲国产欧美在线| 亚洲欧美在线高清| 久久免费美女视频| 欧美一区二区国产| 精品视频免费看| 91老师片黄在线观看| 国产精品1区2区3区在线观看| 午夜精品久久久久久久久久久| 国产精品色一区二区三区| 日韩一级欧美一级| 色婷婷综合久久久中文字幕| 国产91精品露脸国语对白| 国产精品系列在线观看| 91亚洲大成网污www| 精品一区二区三区av| 无码av中文一区二区三区桃花岛| 亚洲乱码国产乱码精品精98午夜| 欧美国产视频在线| 国产午夜精品在线观看| 亚洲精品一区二区精华| 欧美大胆人体bbbb| 欧美一区二区观看视频| 日韩一二在线观看| 精品免费国产一区二区三区四区| 欧美日韩高清一区| 欧美精品777| 91麻豆精品国产无毒不卡在线观看 | ●精品国产综合乱码久久久久| 337p日本欧洲亚洲大胆精品 | 国产一区视频在线看| 久久成人免费电影| 精品写真视频在线观看| 老司机午夜精品99久久| 久久99久久精品| 国产一区二区成人久久免费影院| 国产剧情一区在线| 国产精品系列在线观看| eeuss鲁片一区二区三区在线观看 eeuss鲁片一区二区三区在线看 | 日本欧美肥老太交大片| 日本中文一区二区三区| 另类中文字幕网| 国产一区二区三区久久久| 成人动漫一区二区三区| 色香蕉久久蜜桃| 欧美电影一区二区| 久久你懂得1024| 激情六月婷婷综合| 国产成人综合自拍| 色一情一伦一子一伦一区| 4438x亚洲最大成人网| 久久蜜桃av一区精品变态类天堂| 国产三级一区二区| 亚洲图片自拍偷拍| 韩日av一区二区| 91美女在线看| 欧美精品乱码久久久久久按摩| 2020国产精品自拍| 亚洲人成电影网站色mp4| 日韩精品一二三| 成人午夜精品在线| 欧美久久婷婷综合色| 久久精品水蜜桃av综合天堂| 亚洲欧美欧美一区二区三区| 午夜激情综合网| 成人99免费视频| 欧美日韩高清在线播放| 久久精品一区二区三区av| 亚洲国产一二三| 国产成a人无v码亚洲福利| 欧美日韩视频一区二区| 国产亚洲成av人在线观看导航| 亚洲网友自拍偷拍| www.在线成人|