C/Cpp / STL / vector 释放内存的方案
答案
1、當 T 為指針時,釋放內存的代碼如下:
for(auto &x:vSum) {delete x; } std::vector<T>().swap(vSum);2、當 T 為原生類型(int、float、char)時,釋放內存的代碼如下:
std::vector<T>().swap(vSum);3、當 T 為類對象時,釋放內存的代碼如下:
vSum.clear(); std::vector<T>().swap(vSum);說明
大家可以看到,釋放內存共用到了兩個函數,分別是 clear() 和 swap()?,弄明白這兩個函數的功能也就清楚了 vector 釋放內存的原理了。
1、clear() 函數(stl_vector.h)
有此可知 clear 函數調用的是 erase 函數。
erase 函數的操作過程是將 last 到 finish 之間的元素移動到 first 元素的位置,然后刪掉從 first + (finish - last) 為開始 finish 之間所有的元素。刪除操作就是由 destory() 函數完成。下面看下 destory 函數的內容。?(stl_construct.h)
我們可以發現 __destroy 比 destroy 多了第3個參數?value_type(first)?,該函數的原型如下:(stl_iterator.h)
該函數的作用是返回 Iterator 的型別,即:數據類型。?好,在深入到?iterator_traits 看下其是如何知道 Iterator 的型別的。(stl_iterator.h)
?上述代碼中的 value_type 就是?vector 類中的?
typedef T value_type;也就是 value_type 函數返回的值就是 T *類型的值為 0 的地址。好,咱們進 __destory() 函數看下
?這里面的關鍵就是代碼
typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;它的作用是返回類型 T 是否含有析構函數!具體可以看其的實現,采用的是模板特化的方案。好了,如果類型 T ,有析構函數,則進入如下代碼,
?若是類型 T 沒有析構函數,則執行如下代碼
所以,經過上述代碼的梳理,我們可以得到結論:clear() 函數實際上是嘗試執行指定范圍內每個要素的析構函數,如果 T 是原生的類型或者是指針,那么 clear() 就不會再做任何事情了。 所以該函數不會釋放 vector 本身申請的內存!那負責釋放內存的工作就落到了?std::vector<T>().swap(vSum);?頭上了!
所以,只有 T 為對象時,執行 clear() 才有意義。當然了,為了節約大腦資源,無論 T 為什么類型,都可以把 clear() 函數加上。
2、swap() 函數。
swap() 函數原型
?該函數的作用就是交換兩個 vector 的 start、finish 和 end_of_storage?。?用在?std::vector<T>().swap(vSum); 上時,相當于 臨時的 vector 對象的 3 個指針指向了 vSum 中的內存,vSum 的?3 個指針指向了臨時對象中的內存(空的),由于該代碼執行完之后,臨時對象就銷毀了,所以就間接完成了釋放 vSum 所申請的內存的目的!
總結
總之一條原則,自己 new 的自己去 delete 釋放;不是自己 new 的,就不該你去釋放。
往 vector 里面插入元素是對象時,vector 會負責執行這些對象的析構函數,因為內存是自己申請的。但是如果存在里面是對象的指針時,因為對象指針指向的對象的內存是程序員自己申請的,所以 vector 不會管(不會執行對象的析構函數)!
上述是 STL 通理。
拓展
源碼網址
?
(SAW:Game Over!)
總結
以上是生活随笔為你收集整理的C/Cpp / STL / vector 释放内存的方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C/Cpp / STL / 模板全特化和
- 下一篇: C/Cpp / STL / 类型萃取