静态分配内存和动态分配内存
? ? ? ? 首先,在使用動態(tài)分配內存技術前,必須明白自己在做什么,這樣做與其它的方法有什么不同,特別是會產生哪些負面影響,天下沒有免費的午餐。動態(tài)分配內存與靜態(tài)分配內存的區(qū)別:
1) 靜態(tài)內存分配是在編譯時完成的,不需要占用CPU資源;動態(tài)分配內存是在運行時完成的,動態(tài)內存的分配與釋放需要占用CPU資源;
2) 靜態(tài)內存分配是在棧上分配的,動態(tài)內存是堆上分配的;
3) 動態(tài)內存分配需要指針或引用數據類型的支持,而靜態(tài)內存分配不需要;
4) 靜態(tài)分配內存需要在編譯前確定內存塊的大小,而動態(tài)分配內存不需要編譯前確定內存大小,根據運行時環(huán)境確定需要的內存塊大小,按照需要分配內存即可。可以這么說,靜態(tài)內存分配是按計劃分配,而動態(tài)內存分配是按需分配。
5) 靜態(tài)分配內存是把內存的控制權交給了編譯器,而動態(tài)內存是把內存的控制權交給了程序員;
綜上所述,靜態(tài)分配內存適合于編譯時就已經可以確定需要占用內存多少的情況,而在編譯時不能確定內存需求量時可使用動態(tài)分配內存;但靜態(tài)分配內存的運行效率要比動態(tài)分配內存的效率要高,因為動態(tài)內存分配與釋放需要額外的開銷;動態(tài)內存管理水平嚴重依賴于程序員的水平,如果處理不當容易造成內存泄漏。那么再具體些,如何選擇內存分配方式,如果動態(tài)分配內存需要注意哪些問題呢?
需要強調的是,由于動態(tài)分配內存把內存的控制權交給了程序員,程序員有義務寫代碼確認內存分配成功能,如果分配失敗要做適當處理,否則將給你的程序進而下一個定時炸彈,隨時有可能因為動態(tài)內存分配失敗而導致程序崩潰。
1. 全局變量盡可能不要動態(tài)分配內存。
既然將變量定義為全局變量,就為了其可見范圍比較寬,因為可能這些變量在整個程序的運行期都是可見的,可能根本就沒有機會釋放全局變量所占用的內存,所以使用動態(tài)分配內存是意義不大的,只能給程序帶來額外的運行負擔。
但對于全局變量內存大小不能確定的情況,可能會有例外。比如要處理一批數據,數據的大小可能由用戶通過控制臺參數形式告訴程序,這種情況可以動態(tài)按需分配內存,合理使用內存。
而對于編譯時能夠確定內存使用量的全局變量,而且變量工作期(暫且這么叫吧,就是該變量還可能會被用到的這段時期)又與程序的運行期相同的情況根本沒有必要動態(tài)分配內存。這種情況很有意思,就是使用動態(tài)分配內存,但可以不考慮釋放這塊內存,因為可以釋放內存的時候該程序也要退出了,程序一結束,進程也就結束了,整個程序所在的虛擬空間已經被全部釋放,也就沒必要去添加釋放內存的代碼了。(但我確定見到過這樣的代碼)
2. 動態(tài)分配內存時,分配與釋放的代碼要對稱。
這里說的分配與釋放的代碼對稱指,分配內存的代碼要與釋放內存的代碼在同一個范圍的代碼域中,例如在一個函數的開頭申請內存,就應該在這個函數的結尾釋放內存,否則,如果在一個函數內部分配內存,在函數外釋放內存,就有可能因程序員的疏忽造成內存泄漏;如果內存分配在某個類的構造函數中,那么就應該在析構函數中釋放內存,千不要在另外一個函數中釋放,而等著客戶代碼去掉用那個函數去手動釋放內存,如果那樣的話就相當于埋了一個定時炸彈,隨時可能因為一時的疏忽而造成內存泄漏。
3. 對動態(tài)創(chuàng)建的對象或分配的內存塊一定要檢查期有效性。
由于操作系統的并發(fā)性和復雜性,任何一次動態(tài)內存的分配操作都有可能失敗,特別是申請一次較大塊內存時。所以一定要檢查動態(tài)創(chuàng)建的對象或申請的堆內存是否成功,否則可能因為錯誤的指針或空指針造成程序異常,如果異常沒有得到適當處理的話,可能使整個程序意外終止,造成損失。
4. 盡可能少次數地使用動態(tài)內存分配。
動態(tài)分配是在運行時由操作系統完成的,所以是要消耗CPU資源的,在進行動態(tài)內存分配時盡可能便利已經分配的資源。如果上次申請的資源夠用就不要重新申請資源,不夠用時才釋放舊資源,申請新資源。
5. 在保證資源利用率的前提下,能用靜態(tài)內存分配不用動態(tài)分配,特別是局部臨時對象。
例如,對于局部對象,使用靜態(tài)分配的內存,可以由編譯器編譯時分配,超出作用域自動內存,不僅減小了程序代碼,減少了錯誤產生的概率,減輕了程序員的負擔,而且提高的程序的執(zhí)行效率,何樂而不為呢?
總結
以上是生活随笔為你收集整理的静态分配内存和动态分配内存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: define宏定义和const定义之间的
- 下一篇: ubuntu下交叉编译环境构建