最近跑一個程式,結果2G記憶體用完了,結果也沒算出來,出現std::bad_alloc,應該是程式中某個地方記憶體空間沒有及時釋放,開始檢查程式。發現好多地方用到vector,而且有些會很大,並且只是中間結果,只是因為需要在多個地方訪問,定義為了類的成員變數,要等到這個類解析的時候才釋放空間,看來應該在程式中,它的中間作用結束之後便釋放記憶體。於是開始探索如何釋放vector的記憶體。
1、vector的成員函數 clear()
clear()只是清除vector中的變數,並不釋放記憶體。一個簡單的測試程式如下,
int main(){
vector<double> a;
for(unsigned int i=0;i<10;i++){
a.push_back(i+i/10);
}
cout << a.size() << " " << a.capacity() << endl;
a.clear(); cout << a.size() << " " << a.capacity() << endl; return 0;
}
輸出是:
10 16
0 16
size給出vector中的元素個數,capacity給出vector佔用的記憶體大小,單位是vectot中的元素類型佔用的記憶體大小。
可以看到,vector申請的記憶體空間並不是與元素個數相等,vector的記憶體空間是可以動態增長的,比如一開始vector<double> a只申請了4個double的空間,當元素個數超過4個時,vector重新分配記憶體。最後有10個元素時,vector佔用16個double的空間。當執行clear之後,元素個數為0,但佔用的記憶體空間沒變,也就是說,vector<double> a佔用的記憶體空間沒有得到釋放。由於它不是new申請的空間,所以不能使用delete。那麼該如何釋放這樣的記憶體空間呢?
2、swap方法
在 http://topic.csdn.net/u/20091202/15/817018d4-e0fc-4229-94b7-0869c9366a53.html 給出了兩種釋放vector佔用記憶體的方法,試用了一下。
a.swap(vector<double>());
編譯的時候報錯了, error: no matching function for call to ‘std::vector<double, std::allocator<double> >::swap(std::vector<double, std::allocator<double> >)’/usr/include/c++/4.4/bits/stl_vector.h:929: note: candidates are: void std::vector<_Tp, _Alloc>::swap(std::vector<_Tp, _Alloc>&) [with _Tp = double, _Alloc = std::allocator<double>]
swap的參數應該是一個vector的引用,雖然swap是通過將vector<double> a與一個臨時變數的空間交換,交換之後,a的空間為0,臨時變數的空間為a之前的空間,然後臨時變數在這個過程結束的時候,記憶體空間被釋放。這樣達到釋放a的空間,在a不是臨時變數的時候。將上面的一條語句改為兩條,
vector<double> b;
a.swap(b);
這樣便不會報錯了。這是引用和值傳遞的區別。
文章中還給出了一種方法,試了一下,佔用空間沒有改變,不知道為什麼。連結給出的文章講了部分內容,可做參考。 http://oss.org.cn/?action-viewnews-itemid-3744
3、數組元素為指標的時候的記憶體釋放
很多時候,我們會用vector儲存一組指標,
vector<classType*> S;
{
classType *item = new classType();
S.push_back(item);
}
這個時候,swap也只是清空這些指標佔用的空間,但指標指向的類的執行個體占的空間是沒有被釋放的。對於這種vector,需要手動地釋放這些空間。
classType *item = NULL;
for(i=0;i<S.size();i++){
item = S[i]; //釋放vector指標元素指向的空間
delete (classType*) item;
}vector<classType*> Stmp;//釋放vector佔用的空間S.swap(Stmp);
在一個函數內部,臨時變數在函數退出時釋放記憶體,如果想儘快釋放掉記憶體,可以考慮用new申請臨時變數的空間,然後儘快delete。如下,
vector<classType*> *Stemp = new vector<classType*>();
S.swap(*Stmp);
for(i=0;i<Stmp->size();i++){
delete (clasType*) (*Stmp)[i];
}
delete vector<classType*> Stmp;
第三部分的內容只是想法,還沒有驗證。