1. 程式人生 > 其它 >vector 記憶體分配和釋放

vector 記憶體分配和釋放

最近學習了Vector的使用,在通用函式的背後,你瞭解它的工作機理麼,你能回答下面幾個問題麼。如何不慎清楚,請看下文之簡單剖析。後續問題和疑問,將在文後補充。

Q:是巢狀的vector陣列中的二級vector在一級vector刪除時需不需要手動刪除?
A:釋放遵循有內到外,只有vector存的是指標時才需要釋放,其它不需要釋放


Q:erase clear 能釋放記憶體麼?
earse 是不釋放記憶體的 僅僅清理資料
可是使用clear釋放vector記憶體有是問題的,可參考c++標準:
clear只是將vector的size置零,可是並不保證capacity為零,因此clear並不能釋放vector已經申請的記憶體。可使用vector<T>().swap(x)完成釋放記憶體的操作。
考慮用swap()來幫助釋放記憶體‘

C++ vector 記憶體分配與回收機制

https://blog.csdn.net/sinat_33718563/article/details/77869145

https://blog.csdn.net/wskzgz/article/details/113122684 //c++ vector記憶體分配、記憶體分佈堆疊
1. vector記憶體增長


vector所有的記憶體相關問題都可以歸結於它的記憶體增長策略。vector有一個特點就是:記憶體空間只會增長不會減少。vector有兩個函式,一個是capacity(),
返回物件緩衝區(vector維護的記憶體空間)實際申請的空間大小,另一個size(),返回當前物件緩衝區儲存資料的個數。
對於vector來說,capacity是永遠大於等於size的,但capacity和size相等時,vector就會擴容,capacity變大。
比如說vector最常用的push_back操作,它的整個過程是怎麼一個機制呢?這個問題經常在面試中出現。
這個問題其實很簡單,在呼叫push_back時,若當前容量已經不能夠放入新的元素(capacity=size),那麼vector會重新申請一塊記憶體,把之前的記憶體裡的元素拷貝到新的記憶體當中,
然後把push_back的元素拷貝到新的記憶體中,最後要析構原有的vector並釋放原有的記憶體。
所以說這個過程的效率是極低的,為了避免頻繁的分配記憶體,C++每次申請記憶體都會成倍的增長,例如之前是4,那麼重新申請後就是8,以此類推。當然不一定是成倍增長


在呼叫push_back時,每次執行push_back操作,相當於底層的陣列實現要重新分配大小;
這種實現體現到vector實現就是每當push_back一個元素,都要重新分配一個大一個元素的儲存,
然後將原來的元素拷貝到新的儲存,之後在拷貝push_back的元素,最後要析構原有的vector並釋放原有的記憶體。

2. 記憶體釋放


就像前面所說的,vector的記憶體空間是隻增加不減少的,我們常用的操作clear()和erase(),實際上只是減少了size(),清除了資料,並不會減少capacity,所以記憶體空間沒有減少。
那麼如何釋放記憶體空間呢,正確的做法是swap()操作。
標準模板如下

template < class T >
void ClearVector( vector< T >& vt )
{
vector< T > vtTemp;
veTemp.swap( vt );
}

例子:

vector<int> nums;
nums.push_back(1);
nums.push_back(1);
nums.push_back(2);
nums.push_back(2);
vector<int>().swap(nums); //或者nums.swap(vector<int> ())

3.總結


由上可見,vector雖然是動態陣列,但是本質上和陣列沒什麼區別,頻繁的銷燬新建,效率很低,所以正確的做法是新建vector的時候初始化一個合適的大小(笑),
回到了陣列的老路上。不過之後可以動態變化還是很方便,而且還有很多好用的函式。vecotr是動態陣列,顧名思義他可以動態的增加自己的長度。


Vector系列記憶體佈局分析
https://www.leadroyal.cn/p/181/
https://lunatic.blog.csdn.net/article/details/88556426