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