在C++編程語言中,對於內存的操作是一個非常重要的應用技術,作為程序員來說,必須要清楚這方面的應用。在這裡我們先來介紹一下C++內存使用機制的相關概念,希望能給大家帶來一些幫助。
1.程序使用內存區
一個程序占用的內存區一般分為5種:
1)全局、靜態數據區:存儲全局變量及靜態變量包括全局靜態變量和局部靜態變量)
2)常量數據區:存儲程序中的常量字符串等。
3)代碼區:存儲程序的代碼。
4)棧:存儲自動變量或者局部變量,以及傳遞的函數參數等。
5)堆:存儲動態產生的數據。
在處理內存時,系統會自動將內存對齊,這樣雖然會浪費一些內存,但由於CPU在對齊方式下運行比較快,所以一般都是對程序性能還是有好處的。
一個程序使用的棧的大小是固定的,由編譯器決定。一般是1MB。棧的內存是系統自動分配的,壓棧和出棧都有相應的指令進行操作。因此效率較高,並且分配的內存空間是連續的,不會產生內存碎片;而堆上的內存是由開發人員來動態分配和回收的。在分配內存時,系統需要按照一定的算法在堆空間中尋找合適大小的空閒堆,並修改相應的維護堆空閒空間的鏈表,然後返回地址給程序。因此效率比棧要低,此外還容易產生內存碎片。
從C++對象模型的角度來說,對象就是C++內存使用機制中的一片區域。如果一個對象通過定義在某個函數內的變量或者實現需要的臨時變量來創建時,它是棧上的一個對象;如果一個對象是定義在全局范圍內的變量,則它是存儲全局/靜態數據區;如果一個對象是通過new操作符來創建時,它是堆上的一個對象。
2.對象的生命周期
1)通過定義變量創建對象:在這種情況下,變量的作用域決定了對象的生命周期。當進入變量的作用域時,對象被創建。而退出變量的作用域時,對象被銷毀。值得注意的是靜態變量和全局變量,由於全局變量的作用域是整個程序,因此被聲明為全局變量的對象在程序調用main()函數之前被創建。當程序退出main()函數之後,全局對象才被銷毀。靜態對象與全局對象類似,雖然靜態變量的作用域不是整個程序,但靜態變量是存儲在全局/靜態數據區中,在程序開始時已經分配好。因此聲明為靜態變量的對象第一次進入作用域時被創建,直到程序退出時被銷毀。
2)通過new操作符創建對象:這種情況相對比較簡單,但也最容易造成內存洩漏。通過new創建的對象會一直存在,直到被delete銷毀。即使指向該對象的指針一般都是自動變量)已被銷毀,但還沒有調用delete,該對象就會一直存在。即占據內存空間,直到程序退出,因此也就造成內存洩漏。
3)通過實現創建對象:這種情況一般是指一些隱藏的中間臨時變量的創建和銷毀。它們的生命周期很短,也不容易被開發人員發覺。但常常是造成程序性能下降的瓶頸,尤其是對於那些占用內存較多,創建速度較慢的對象。這些臨時對象一般是通過copy constructor創建的。在實際開發中,通過值傳遞傳遞參數,重載+及++等操作符,對對象進行算術運算時,也會有臨時對象,對於這些情況,都要盡量避免不必要的臨時對象的出現。
3.C++對象的內存布局
1)非靜態數據成員是影響對象占據內存大小的主要因素,隨著對象數目的增加,非靜態數據成員占據的內存會相應增加。
2)所有的對象共享一份靜態數據成員,所以靜態數據成員占據的內存的數量不會隨著對象數目的增加而增加。
3)靜態成員函數和非靜態成員函數不會影響對象內存的大小,雖然其實現會占據相應的C++內存使用機制空間,同樣也不會隨著對象數目的增加而增加。
4)如果對象中包含虛函數,會增加4個字節的空間虛函數表指針),不論有多少個虛函數。