freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內(nèi)容

unit07動態(tài)分配內(nèi)存空間(已修改)

2025-05-26 19:35 本頁面
 

【正文】 第七章 動態(tài)內(nèi)存分配與數(shù)據(jù)結(jié)構(gòu) 本章首先介紹程序運行時 動態(tài)內(nèi)存分配 ( dynamic memory allocation)的概念與方法。進一步討論復制構(gòu)造函數(shù) . 然后學習更多有關(guān) 數(shù)據(jù)結(jié)構(gòu) 的基本知識,包括 鏈表 ,棧 , 隊 , 二叉樹 等的基本算法和應用。 模板 是標準C++實現(xiàn)代碼復用的有力工具,特別是有關(guān)數(shù)據(jù)結(jié)構(gòu)的算法,本章繼續(xù)使用。 (選讀) 棧與隊列的基本操作及其應用 鏈表與鏈表的基本操作 第七章 動態(tài)內(nèi)存分配與數(shù)據(jù)結(jié)構(gòu) 內(nèi)存 的分配與釋放 對象 與構(gòu)造函數(shù) 淺復制與深復制 靜態(tài)存儲分配: 通常定義變量 (或?qū)ο?),編譯器在編譯時都可以根據(jù)該變量 (或?qū)ο?)的類型知道所需內(nèi)存空間的大小,從而系統(tǒng)在適當?shù)臅r候為它們分配確定的存儲空間。 動態(tài)存儲分配: 有些操作對象只有在程序運行時才能確定,這樣編譯器在編譯時就無法為他們預定存儲空間,只能在程序運行時,系統(tǒng)根據(jù)運行時的要求進行內(nèi)存分配,稱為動態(tài)存儲分配。動態(tài)分配都在 自由存儲區(qū) 中進行。 內(nèi)存的分配與釋放 當程序運行到需要一個動態(tài)分配的變量或?qū)ο髸r , 必須向系統(tǒng) 申請取得自由存儲區(qū) 中的一塊所需大小的存貯空間 , 用于存貯該變量或?qū)ο?。 當不再使用該變量或?qū)ο髸r , 也就是它的生命結(jié)束時 , 要 顯式釋放 它所占用的存貯空間 , 這樣系統(tǒng)就能進行再次分配 , 做到重復使用有限的資源 。 申請和釋放 自由存儲區(qū) 中分配的存貯空間,分別使用 new和 delete的兩個運算符來完成,其使用的格式如下: 指針變量名 =new 類型名 (初始化式 ); delete 指針名 。 new運算符 返回 的是一個指向所分配類型變量(對象)的指針 。對所創(chuàng)建的變量或?qū)ο?,都是通過該指針來間接操作的,而 動態(tài)創(chuàng)建的對象本身沒有名字。 動態(tài)分配與釋放: 內(nèi)存的分配與釋放 一般定義變量和對象時要用標識符命名,稱 命名對象 ,而動態(tài)的稱 無名對象 (請注意與棧區(qū)中的臨時對象的區(qū)別,兩者完全不同:生命期不同,操作方法不同,臨時變量對程序員是透明的 )。 自由存儲區(qū) 是不會自動在分配時做初始化的(包括清零),所以必須用初始化式 (initializer)來顯式初始化。 new表達式的操作: 從自由存儲區(qū)分配對象,然后用括號中的值初始化該對象 。 分配對象時, new表達式調(diào)用庫操作符 new(): int *pi=new int(0)。 pi現(xiàn)在所指向的變量的存儲空間是由庫操作符 new()分配的,位于程序的自由存儲區(qū)中,并且該對象未命名。 無名對象: 內(nèi)存的分配與釋放 自由存儲區(qū) 0 P i 演示: 1.用初始化式 (initializer)來顯式初始化 int *pi=new int(0)。 2 . 當 pi生命周期結(jié)束時 , 必須釋放 pi所指向的目標: delete pi。 注意這時釋放了 pi所指的目標的內(nèi)存空間,也就是撤銷了該目標,稱動態(tài)內(nèi)存釋放( dynamic memory deallocation),但 指針 pi本身并沒有撤銷 ,該指針所占內(nèi)存空間并未釋放。 內(nèi)存的分配與釋放 數(shù)組動態(tài)分配格式: 指針變量名 =new 類型名 [下標表達式 ]。 Delete[ ] 指向該數(shù)組的指針變量名 。 說明: 兩式中的 方括號 必須配對使用 。 如果 delete語句中少了方括號 , 因編譯器認為該指針是指向數(shù)組第一個元素的指針 , 會產(chǎn)生 回收不徹底 的問題 ( 只回收了第一個元素所占空間 ) , 加了方括號后就轉(zhuǎn)化為指向數(shù)組的指針 , 回收整個數(shù)組 。 delete [ ]的方括號中 不需要 填 數(shù)組元素數(shù) ,系統(tǒng)自知。即使寫了,編譯器也忽略。 請注意 “下標表達式”不是常量表達式 ,即它的值不必在編譯時確定, 可以在運行時確定 。 內(nèi)存的分配與釋放 動態(tài)分配數(shù)組與 標準字符串類 : 標準字符串類 string就是采用動態(tài)建立數(shù)組的方式解決數(shù)組溢出的問題的,例 ,在 string類對象中都是自動完成的,在程序中不需要也不允許再顯式地為 string進行動態(tài)內(nèi)存的分配與釋放。 【 例 】 動態(tài)數(shù)組的建立與撤銷 內(nèi)存的分配與釋放 動態(tài)分配數(shù)組的特點: 1. 變量 n在編譯時沒有確定的值,而是在運行中輸入, 按運行時所需分配空間 ,這一點是動態(tài)分配的優(yōu)點,可克服數(shù)組“大開小用”的弊端,在表、排序與查找中的算法,若用動態(tài)數(shù)組,通用性更佳。 delete [ ]pc是將 n個字符的空間釋放,而用 delete pc則只釋放了一個字符的空間; 2. 如果有 char *pc1,令 pc1=pc,同樣可用 delete [ ] pc1 來釋放該空間。盡管 C++不對數(shù)組作邊界檢查,但 在 自由 存儲區(qū) 空間分配時,對數(shù)組分配空間大小是紀錄在案的 。 3. 沒有初始化式( initializer), 不可對數(shù)組初始化 。 內(nèi)存的分配與釋放 (選讀) 多維數(shù)組動態(tài)分配: new 類型名 [下標表達式 1] [下標表達式 2]……。 建立一個動態(tài)三維數(shù)組 float (*cp)[30][20] 。 //指向一個 30行 20列數(shù)組的指針 cp=new float [15] [30] [20]。 //建立由 15個 30*20數(shù)組組成的數(shù)組; 注意 cp等效于三維數(shù)組名,但沒有指出其邊界,即最高維的元素數(shù)量,就像指向字符的指針即等效一個字符串 ,不要把指向字符的指針,說成指向字符串的指針 。這與數(shù)組的嵌套定義相一致。 內(nèi)存的分配與釋放 (選讀) 比較: float(*cp) [30] [20]。 //三級指針 float (*bp) [20]。 //二級指針 cp=new float [1] [30] [20]。 bp=new float [30] [20]。 兩個數(shù)組都是由 600個浮點數(shù)組成,前者是只有 一個元素的三維數(shù)組 ,每個元素為 30行 20列的二維數(shù)組,而另一個是有 30個元素的二維數(shù)組 ,每個元素為 20個元素的一維數(shù)組。 刪除這兩個動態(tài)數(shù)組可用下式: delete [] cp。 //刪除(釋放)三維數(shù)組 delete [] bp。 //刪除(釋放)二維數(shù)組 【 例 】 動態(tài)創(chuàng)建和刪除一個 m*n個元素的數(shù)組 的分配與釋放 指針使用的要點: 1. 動態(tài)分配失敗 。返回一個空指針( NULL),表示發(fā)生了異常,堆資源不足,分配失敗。 2. 指針刪除與 自由存儲區(qū) 空間釋放 。刪除一個指針 p( delete p。)實際意思是刪除了 p所指的目標(變量或?qū)ο蟮龋?,釋放了它所占?自由存儲區(qū) 空間,而不是刪除p本身,釋放自由存儲區(qū)空間后,p成了 空懸指針 ??諔抑羔樖浅绦蝈e誤的一個根源)。建議這時將p置空( NULL)。 3. new()和 delete()是可以重載的 ,它們都是類的靜態(tài)成員函數(shù)。程序員無需顯式聲明它為靜態(tài)的,系統(tǒng)自動定義為靜態(tài)的。本教材不討論 new()和 delete()的重載。未重載時,調(diào)用全局庫操作符 new()。 內(nèi)存的分配與釋放 4. 內(nèi)存泄漏( memory leak)和重復釋放 。 new與 delete 是配對使用的, delete只能釋放 自由存儲區(qū) 空間。如果 new返回的指針值丟失,則所分配的 自由存儲區(qū) 空間無法回收,稱內(nèi)存泄漏,同一空間重復釋放也是危險的,因為 該空間可能已另分配 ,所以必須妥善保存 new返回的指針,以保證不發(fā)生內(nèi)存泄漏,也必須保證不會重復釋放自由存儲區(qū) 內(nèi)存空間。 5. 動態(tài)分配的變量或?qū)ο蟮纳?。 無名對象的生命期并不依賴于建立它的作用域,比如在函數(shù)中建立的動態(tài)對象在函數(shù)返回后仍可使用 。但必須記住釋放該對象所占 自由存儲區(qū) 空間,并只能釋放一次,在函數(shù)內(nèi)建立,而在函數(shù)外釋放是一件很容易 失控 的事,往往會出錯。 對象與構(gòu)造函數(shù) 類對象動態(tài)建立與刪除過程: 通過 new建立的對象要調(diào)用構(gòu)造函數(shù),通過 delete刪除對象也要調(diào)用析構(gòu)函數(shù)。 CGoods *pc。 pc=new CGoods。 //分配自由存儲區(qū)空間,并構(gòu)造一個無名的 CGoods對象; ……. delete pc。 //先析構(gòu),然后將內(nèi)存空間返回給自由存儲區(qū); 自由存儲區(qū) 對象的生命期并不依賴于建立它的作用域,所以除非程序結(jié)束, 自由存儲區(qū) 對象(無名對象)的生命期不會到期,并且需要顯式地用 delete語句析構(gòu)該類對象,上例執(zhí)行 delete語句時, C++自動調(diào)用商品類的析構(gòu)函數(shù)。 對象與構(gòu)造函數(shù) 由自由存儲區(qū)創(chuàng)建對象數(shù)組 , 只能調(diào)用默認的構(gòu)造函數(shù) , 不能調(diào)用其他任何構(gòu)造函數(shù) 。 如果沒有默認的構(gòu)造函數(shù) , 則不能創(chuàng)建對象數(shù)組 。 類對象初始化: new后面類( class)類型可以有參數(shù)。這些參數(shù)即構(gòu)造函數(shù)的參數(shù)。但對 創(chuàng)建數(shù)組 ,則無參數(shù), 只能調(diào)用默認的構(gòu)造函數(shù) 。 【 例 】 演示自由存儲區(qū)對象分配和釋放。 淺復制與深復制 淺復制: 默認復制構(gòu)造函數(shù) ,可用一個類對象初始化另一個類對象,稱為默認的 按成員復制, 而不是對整個類對象的 按位復制。 這稱為 淺復制。 圖 淺復制 P 自 由存儲 區(qū)對象 自 由 存儲區(qū) 對象 P P 復制前 復制后 如果類中有一個數(shù)據(jù)成員為指針,該類的一個對象 obj1中的這個指針 p,指向了動態(tài)分配的一個 自由存儲區(qū) 對象,(參見圖 ),如果用 obj1按成員復制了一個對象 obj2,這時 自由存儲區(qū) 對象。 obj1 obj1 obj2 淺復制與深復制復制 當 淺復制 析構(gòu)時,如用默認的析構(gòu)函數(shù),則動態(tài)分配的 自由存儲區(qū) 對象不能回收。如果在析構(gòu)函數(shù)中有“ delete p?!闭Z句,則如果先析構(gòu)函數(shù) obj1時,自由存儲區(qū) 對象已經(jīng)釋放,以后再析構(gòu)obj2時出現(xiàn)了二次釋放的問題。 自由存儲區(qū) 對象 P P 自由存儲區(qū) 對象 圖 深復制 深復制: 重新定義復制的構(gòu)造函數(shù),給每個對象獨立分配一個 自由存儲區(qū)對象,稱 深復制 。 這時先復制對象主體,再為 obj2分配一個 自由存儲區(qū) 對象,最后用 obj1的 自由存儲區(qū) 對象復制 obj2的 自由存儲區(qū) 對象。 obj1 obj2 淺復制與深復制 【 例 】 定義復制構(gòu)造函數(shù) ( copy structor)和復制賦值操作符( copy Assignment Operator)實現(xiàn)深復制。 學生類定義: class student{ char *pName。 //為了演示深復制,不用 string類 public: student()。 //默認構(gòu)造函數(shù) student(char *pname)。 //帶參數(shù) 構(gòu)造函數(shù) student(student amp。s)。 //復制構(gòu)造函數(shù) ~student()。 //析構(gòu)函數(shù) student amp。 operator=(student amp。s)。 }。 //復制賦值操作符 檢驗 主函數(shù) 和 運行結(jié)果 淺復制與深復制 提示: 自由存儲區(qū)內(nèi)存是最常見的需要自定義復制構(gòu)造函數(shù)的資源,但不是唯一的,還有打開文件等也需要自定義復制構(gòu)造函數(shù)。 如果類對象需要動態(tài)分配資源應該由構(gòu)造函數(shù)完成,而釋放資源由析構(gòu)函數(shù)完成,這時類也需要一個自定義的復制構(gòu)造函數(shù),實現(xiàn)對象的深復制。由此可見, 構(gòu)造函數(shù)并非僅做初始化工作 。 淺復制與深復制 思考: 深入地考慮 【 例 】 ,如果數(shù)據(jù)域還有很多其他數(shù)據(jù),甚至有好幾個是動態(tài)建立的 C字符串,深復制是不是太復雜了?如果使用 C++標準字符串 string作為成員對象(聚合) 是否就不需要考慮深復制了? 的確是這樣的,準確地說, string類的內(nèi)部包含動態(tài)建立字符數(shù)組的操作,其復制構(gòu)造函數(shù)是深復制。如果在 student類中使用 string類而不是 C字符串,就不要再考慮深復制問題了。也就是說,動態(tài)內(nèi)存分配和深復制應該放在一個適當?shù)膶用嫔?,一個更單純的類定義中,如 string類。在使用中,把它作為一個成員對象,就像使用 string類對象那樣。 淺復制與深復制 探討: 最后進一步討論類的封裝。封裝的更高境界是在該類對象中一切都是完備的、自給自足的,不僅有數(shù)據(jù)和對數(shù)據(jù)的操作,還包括資源的動態(tài)安排和釋放。在需要時可以無條件地安全使用。標準string類模板就是典型的例子。這樣的類對象,作為另一個類的成員對象使用時,就不會出任何問題。這表明 聚合
點擊復制文檔內(nèi)容
高考資料相關(guān)推薦
文庫吧 www.dybbs8.com
公安備案圖鄂ICP備17016276號-1