Vector清空資料與釋放記憶體(.clear與.swap的區別與使用)
0)簡單介紹
在vector的資料結構中,
.clear();清空資料
.size();當前vector容器記憶體儲的元素的個數
.capacity();當前vector容器重新分配記憶體之前所能容納的元素數量
.swap();函式交換
1)問題
在用vector做題時,輸入完一組資料處理完後,及時clear(),然後輸入下一組資料,但是如果在輸入之前,輸出之前vector所存的內容,會發現仍然存在,但是如果輸出.empty();它會返回1,告訴我們這個容器現在是空的,這是因為使用.clear()清空內容,但是沒有釋放記憶體的原因。舉例如下:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector <int >a;
cout<<a.empty()<<endl;//輸出 1 代表該vector此時是空
a.push_back(1);
a.push_back(2);
cout<<a[0]<<" "<<a[1]<<endl;//輸出1 2
cout<<a.empty()<<endl;//輸出 0 代表該vector此時非空
cout<<a.size()<<endl;//輸出2
cout<<a.capacity()<<endl;//輸出2
cout<<"***************"<<endl;
//a[0]=NULL;a[1]=NULL; 這是賦值為0,並不清空資料,也不釋放記憶體。
a.clear();
cout<<a[0]<<" "<<a[1]<<endl;//仍然輸出1 2,因為沒有釋放記憶體,所以輸出該地址的內容仍然與之前一樣
cout<<a.empty()<<endl;//輸出1 代表該vector此時已經為空
cout<<a.size()<<endl;//輸出0,代表當前容器記憶體儲元素個數是0,與.empty()類似,都告訴我們當前容器是空的意思
cout<<a.capacity()<<endl;//輸出2,代表當前該vector在重新分配儲存空間前所能容納的元素數量並沒有改變
cout<<"***************"<<endl;
/*
下面這五行說明,.pop_back()與.clear()起到了相同的作用,都是清空資料,但是沒有釋放記憶體
while(!a.empty()){
a.pop_back();
}
cout<<a.empty()<<endl;//輸出 1 代表該vector此時已經為空
cout<<a[0]<<" "<<a[1]<<endl;//仍然輸出為 1 2,因為沒有釋放記憶體,所以輸出該地址的內容仍然與之前一樣
*/
a.push_back(4);
cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;//輸出 4 2 0 儘管沒有釋放記憶體,但是已經認為該vector已經被清空,所以再push_back();時,a[0]被覆蓋。
cout<<a.size()<<endl;//輸出1,代表當前容器記憶體儲元素個數是1,就是剛剛push_back();裝進去的數起到的作用
cout<<a.capacity()<<endl;//此時仍然輸出2
cout<<"***************"<<endl;
//那麼如何釋放記憶體呢?我們用swap交換到一個新的型別的vector,將原來的a拷貝出去,然後自然銷燬,而新的到的a是全新的沒有存任何資料的
vector<int>().swap(a);
//a.swap();
cout<<a.size()<<endl;//輸出 0
cout<<a.capacity()<<endl;.// 輸出 0
//cout<<a[1]<<endl;
}
2)處理辦法
So,如果我們只是做題,.clear();就可以繼續輸入下一組資料了,儘管佔據的記憶體大小不一定是我們希望的大小(不是輸入新的資料後應該佔據的記憶體大小),但一般不會影響到做題。
如果我們想得到一個全新的該vector,那就用1)中code最後展示的一部分,用.swap();重新拷貝一個全新的vector,然後原有的vector會被自然銷燬。另一個解決方法就是在每一次重新輸入資料之前,我們都重新定義,當然這不是讓你在一個作用域內將同名函式重定義(會報錯),我們是指在比如for的每次迴圈的開頭重新定義,讓他們處在不同作用域,如下:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n=10;
while(n--){
vector <int >a;
int k;
cin>>k;
for(int i=1;i<=k;i++){
a.push_back(k);
}
cout<<a.capacity()<<endl;//如果k先後輸入 2 1 那麼我們輸出的vector佔據的記憶體大小先後輸出 2 1,這說明每一次都是一個全新的vector,當然如果你輸入更多的測試資料比如,8 7 6 5 4 3 2 1,你會發現一個有趣的現象,vector對應輸出的數是8 8 8 8 4 4 2 1,這是合理的,作業系統一課中曾經學到過這樣一個分配記憶體空間的辦法,就是每次分配的大小都介於2^n與2^(n+1)之間,這與vector分配空間有相通之處(參考下面的3))。
}
}
3)關於vector儲存資料以及用.swap()釋放記憶體的原理解釋
vector由於是一個不定長儲存的資料結構,每一次分配的大小都是比面前輸入的資料個數略大一點(實際上也並不準確,參看2)code中註釋,是介於2^n與2^(n+1)之間),所以每一次push_back()且發現當被分配的儲存空間已裝滿資料時,都是將包含現有資料的vector進行拷貝,進入一個更大一點的vector,而原有的vector就會被自然銷燬,我們用.swap()釋放記憶體的原理其實是相似的,即手動進行了一次人工拷貝的操作。
相關文章
- vector 避免記憶體頻繁分配釋放與手動釋放vector記憶體記憶體
- vector clear() 方法 記憶體釋放問題記憶體
- vector 的記憶體釋放記憶體
- 記憶體動態分配與釋放,malloc和new區別記憶體
- 記憶體的分配與釋放,記憶體洩漏記憶體
- 正確釋放Vector的記憶體記憶體
- C++ Vector怎麼樣釋放記憶體,通過swap()函式C++記憶體函式
- 記憶體的SDR與DDR的區別記憶體
- 資料型別、記憶體與拷貝資料型別記憶體
- /dev/shm與swap的區別dev
- JVM執行時資料區探索與直接記憶體的使用JVM記憶體
- Vector() 記憶體釋放 不得不說的故事記憶體
- C++ vector 釋放記憶體的兩種方法C++記憶體
- 基本資料型別與引用資料型別,及記憶體分配資料型別記憶體
- Java記憶體區域與記憶體溢位異常 - 執行時資料區Java記憶體溢位
- 清空Oracle記憶體區Oracle記憶體
- 【c++】vector.clear()的記憶體洩露問題C++記憶體洩露
- ARRAYLIST VECTOR LINKEDLIST 區別與用法
- C++學習之路(vector::clear和vector::erase的區別)C++
- Java中Vector與ArrayList的區別詳解Java
- 〈%# 〉與〈%= 〉的區別,顯示資料與繫結資料
- 資料倉儲、資料湖與湖倉一體的區別與聯絡
- JAVA記憶體區域與記憶體溢位異常Java記憶體溢位
- JVM-記憶體區域與OOMJVM記憶體OOM
- Java記憶體區域與分配策略Java記憶體
- PHPCookie與Session的使用與區別PHPCookieSession
- C++ - 二級指標動態記憶體申請與釋放C++指標記憶體
- 宏旺半導體解答ECC與RECC記憶體之間的區別記憶體
- Oracle記憶體分配與使用(zt)Oracle記憶體
- 大資料與海量資料的區別大資料
- “大資料”與“海量資料”的區別大資料
- Arm64記憶體模型、記憶體型別、效能與DMA記憶體模型型別
- Arraylist與Vector的區別 - Java那些事兒專欄Java
- Go:記憶體管理與記憶體清理Go記憶體
- 聊聊 記憶體模型與記憶體序記憶體模型
- JVM(2)-Java記憶體區域與記憶體溢位異常JVMJava記憶體溢位
- 深入理解JVM之記憶體區域與記憶體溢位JVM記憶體溢位
- vector::clear(),容器vector的clear函式詳解。函式