C++ vector容器縮小capacity問(wèn)題
C++ vector容器縮小capacity
vector容器是動(dòng)態(tài)存儲(chǔ)的,跟數(shù)組不同,定義vector的時(shí)候不需要聲明容器的capacity。
首先說(shuō)明一點(diǎn),size是小于等于capacity的,一旦size超過(guò)了capacity,整個(gè)vector容器會(huì)“另辟居所”重新開(kāi)辟更多的空間,這樣也就造成了vector容器首地址發(fā)生改變。
下面是容器的size和capacity的關(guān)系:
#include<iostream> #include<vector> using namespace std; int main() { vector<int> v0; for (int i = 0; i < 100;i++) { v0.push_back(i); } cout << "v0 capacity is " << v0.capacity() << endl;//128 cout << "v0 size is " << v0.size() << endl;//100 vector<int> v1; for (int i = 0; i < 10000;i++) { v1.push_back(i); } cout << "v1 capacity is " << v1.capacity() << endl;//16384 cout << "v1 size is " << v1.size() << endl;//10000 return 0; }
可以看出,vector容器會(huì)根據(jù)你傳入的數(shù)據(jù)數(shù)量進(jìn)行自動(dòng)擴(kuò)展,總是比你存入的數(shù)據(jù)多一些。
但是有一些時(shí)候我們不需要那么多開(kāi)辟好的空間,對(duì)于數(shù)據(jù)size是確定的,這時(shí)候可以用匿名vector交換vector
先介紹一下vector的內(nèi)置函數(shù)swap(),只貼核心代碼了:
vector<int> v1; v1.reserve(10000);//預(yù)設(shè)一個(gè)空間大小 for (int i = 0; i < 100;i++) { v1.push_back(i); } cout << "v1 capacity is " << v1.capacity() << endl;//10000 cout << "v1 size is " << v1.size() << endl;//100 vector<int> v2; v2.reserve(5000); for (int i = 0; i < 50;i++) { v2.push_back(i); } cout << "v2 capacity is " << v2.capacity() << endl;//5000 cout << "v2 size is " << v2.size() << endl;//50 v2.swap(v1); cout << "v1 capacity is " << v1.capacity() << endl;//5000 cout << "v1 size is " << v1.size() << endl;//50 cout << "v2 capacity is " << v2.capacity() << endl;//10000 cout << "v2 size is " << v2.size() << endl;//100
reserve()函數(shù)是預(yù)設(shè)一個(gè)大小,不會(huì)使其反復(fù)開(kāi)辟,當(dāng)然如果后續(xù)超過(guò)這個(gè)預(yù)設(shè)值,vector容器還是會(huì)自動(dòng)開(kāi)辟的。
上面的代碼旨在展示swap()函數(shù)交換的是一整個(gè)容器,包含的是容器的capacity和數(shù)據(jù)的size。
交換縮小vector:
#include<iostream> #include<vector> using namespace std; int main() { vector<int> v1; for (int i = 0; i < 10000;i++) { v1.push_back(i); } cout << "v1 capacity is " << v1.capacity() << endl;//16384 cout << "v1 size is " << v1.size() << endl;//10000 v1.resize(3); cout << "v1 capacity is " << v1.capacity() << endl;//16384 cout << "v1 size is " << v1.size() << endl;//3 vector<int> temp(v1); cout << "temp capacity is " << temp.capacity() << endl;//3 cout << "temp size is " << temp.size() << endl;//3 temp.swap(v1); cout << "v1 capacity is " << v1.capacity() << endl;//3 cout << "v1 size is " << v1.size() << endl;//3 vector<int>(v1).swap(v1);//匿名容器,用后自動(dòng)銷(xiāo)毀。除了沒(méi)有自己的變量名,其他的一樣 cout << "v1 capacity is " << v1.capacity() << endl;//3 cout << "v1 size is " << v1.size() << endl;//3 return 0; }
上面的代碼可以看出:
一個(gè)vector如果是通過(guò)拷貝構(gòu)造的,那么他的size和capacity相同,且等同于被拷貝的那個(gè)容器的size。
結(jié)合上面第二點(diǎn)的發(fā)現(xiàn),swap函數(shù)是一整個(gè)交換的,這樣理論上就可以用temp和v1換,最后使v1的size=capacity,節(jié)省了空間。另外,使用匿名容器更加高效方便。
C++ vector容器的常用用法
vector可以說(shuō)是一個(gè)動(dòng)態(tài)數(shù)組,它可以存儲(chǔ)任何類(lèi)型的數(shù)據(jù),包括類(lèi)!
使用vector需包含頭文件 #include< vector >
.
一、不帶參數(shù)
// 定義了一個(gè)int類(lèi)型的容器 vector<int> v1; // 定義了一個(gè)double類(lèi)型的容器 vector<double> v2;
注意事項(xiàng):容器可以使用數(shù)組方式獲取它的值 和 給它賦值,但是得注意越界!
例如:不可以使用數(shù)組方式給他賦值,因?yàn)槿萜鞑](méi)有給他分配內(nèi)容空間:
vector<int> v1; // 不可以使用數(shù)組方式給他賦值,因?yàn)槿萜鞑](méi)有給他分配內(nèi)容空間 v1[0] = 1; // error // 可以使用數(shù)組方式給他賦值: vector<int> v2(10); v2[0] = 1; // 正確 v2[11] = 11; // 錯(cuò)誤,越界
二、帶參數(shù)
1.定義了一個(gè)int類(lèi)型的容器,定義時(shí)指定給他分配十個(gè)元素的空間
// 定義了一個(gè)int類(lèi)型的容器,定義時(shí)指定給他分配十個(gè)元素的空間 vector<int> v1(10);
默認(rèn)10個(gè)元素都是零值。
2.定義時(shí)指定10個(gè)元素的內(nèi)存,同時(shí)給所有元素賦值666
vector<int> v3(10, 666);
3.定義時(shí)可以使用其他容器來(lái)初始化自己
vector<int> v1(5, 666); // 定義時(shí)可以使用其他容器來(lái)初始化自己 vector<int> v2(v1); // v1 和 v2 相等
4.// 也可以使用 返回迭代器 的方式將一個(gè)容器的元素全都賦值給自己
vector<int> v1(5, 666); vector<int> v2(v1.begin(), v1.end());
5.begin 和 end 返回來(lái)的就是一個(gè)指針迭代器,所以可以進(jìn)行加減操作,指向其他元素的位置
vector<int> v1(5, 666); // 將v1的元素從第三個(gè)元素到最后的元素賦值給v2 vector<int> v2(v1.begin() + 2, v1.end());
6.可以使用數(shù)組來(lái)初始化容器
int Array[5] = {1, 2, 3, 4, 5}; // 將數(shù)組元素1,2,3,4給容器賦初值 vector<int> v1 = (Array, Array+3);
size 獲取容器的元素個(gè)數(shù)
size()
vector<int> v1; v1.size();
capacity 獲取容器的大小
capacity()
vector<int> v1;v1.capacity();
begin 獲取容器第一個(gè)元素的迭代器
begin()
vector<int> v1(10, 666); v1.begin();
end 指向容器最后一個(gè)元素的下一個(gè)位置的迭代器
end()
vector<int> v1(10, 666); v1.end();
assign 賦值玩法
- 第一種玩法 會(huì)改變?cè)瓉?lái)vector中的元素內(nèi)存大小
將v1元素修改為5個(gè),并且賦值888
vector<int> v1(10); v1.assign(5, 888); // 打印結(jié)果5個(gè)888
- 第二種玩法,使用迭代器賦值
將容器v2的10個(gè)1賦值給v1,使得v1和v2相等
vector<int> v1(5); vector<int> v2(10, 1); v1.assign(v2.begin(), v2.end()); // 打印結(jié)果10個(gè)1
- 第三種玩法,使用指針賦值
將數(shù)組的所有元素都賦值給v1
int Array[5] = { 9, 8, 7, 6, 5 }; vector<int> v1; v1.assign(Array, Array + 4); // 打印結(jié)果9,8,7,6,5
- 第四種玩法,使用賦值運(yùn)算符重載
將v1所有元素賦值給v2
vector<int> v1(10, 1); vector<int> v2; v2 = v1; // 打印結(jié)果10個(gè)1
resize 將容器縮小和變大
一、把容器元素縮小
vector<int> v1(10); v1.resize(5); // 縮小長(zhǎng)度為5
二、把容器擴(kuò)大時(shí),并給增加的元素賦值
vector<int> v1(5); v1.resize(8, 111); // 擴(kuò)充v1容器的大小為8,后續(xù)新增加的使用111賦值
三、把容器擴(kuò)大,不給增加的元素賦值
vector<int> v1(5); v1.resize(15);
empty 判斷容器是否為空
為空返回true,為假返回false
vector<int> v1(5); if (v1.empty() == NULL) { cout << "v1為空!" << endl; }
push_back 尾部添加一個(gè)元素
vector<int> v1; v1.push_back(1); // 在尾部增加要給1
pop_back 尾部刪除一個(gè)元素
vector<int> v1(10); v1.pop_back(); // 在尾部刪除一個(gè)元素
at 和數(shù)組使用方式差不多
給第一個(gè)元素賦值1
vector<int> v1(10); v1.at(0) = 1;
打印輸出容器里的所有元素
cout << "v1的所有元素:"; for (int i = 0; i < v1.size(); i++) { cout << v1.at(i) << ", "; }
front 獲取容器的第一個(gè)元素
vector<int> v1(10); v1.front(); // 也可以使用他們賦值 v1.front() = 111; // 給第一個(gè)元素賦值111
back 獲取容器的最后一個(gè)元素
vector<int> v1(10); v1.back(); // 也可以使用他們賦值 v1.back() = 222; // 給最后一個(gè)元素賦值222
insert 元素的插入
vector<int> v1(10); // 往第一個(gè)元素的位置插入一個(gè)5 v1.insert(v1.begin(), 5); // 從第三個(gè)元素位置開(kāi)始插入5個(gè)222 v1.insert(v1.begin() + 2, 5, 222); vector<int> v2(3, 111); // 從第二個(gè)元素開(kāi)始插入v2的所有值 v1.insert(v1.begin() + 1, v2.begin(), v2.end());
erase 與 clear 元素刪除
vector<int> v1(10); // 刪除第一個(gè)元素 v1.erase(v1.begin()); // 刪除第一個(gè)到第三個(gè)元素 v1.erase(v1.begin(), v1.begin() + 3); // 刪除全部元素 v1.clear();
匯總代碼:
#include <iostream> #include <Windows.h> #include <vector> using namespace std; // 不帶參數(shù)的 void text1(void) { vector<int> v1; cout << "v1的元素個(gè)數(shù):"; cout << v1.size() << endl; cout << "v1容器的大?。?; cout << v1.capacity() << endl; v1.push_back(1); v1.push_back(2); cout << endl << "v1插入兩個(gè)元素后:" << endl; cout << "v1的元素個(gè)數(shù):"; cout << v1.size() << endl; cout << "v1容器的大?。?; cout << v1.capacity() << endl; /* 注意: 不可以使用數(shù)組方式給他賦值,因?yàn)槿萜鞑](méi)有給他分配內(nèi)容空間: vector<int> v; v[0] = 1; // error */ } // 帶參數(shù)的 void text2(void) { vector<int> v2(10); // 定義時(shí)指定給他分配十個(gè)元素的空間 cout << "v2的元素個(gè)數(shù):"; cout << v2.size() << endl; cout << "v2容器的大?。?; cout << v2.capacity() << endl; // 里面默認(rèn)的值全為零 cout << "v2里面的元素為:" << endl; vector<int>::iterator it = v2.begin(); for (; it != v2.end(); it++) { cout << *it << ", "; } cout << endl; /* 可以使用數(shù)組方式給他賦值: vector<int> v(10); v[0] = 1; // 正確 */ v2[0] = 1; // 正確 v2[1] = 2; cout << "v2里面的元素為:" << endl; it = v2.begin(); for (; it != v2.end(); it++) { cout << *it << ", "; } cout << endl; /************************************************************************************************/ vector<int> v3(10, 666); // 定義時(shí)指定10個(gè)元素的內(nèi)存,同時(shí)給所有元素賦值666 cout << "v3里面的元素為:" << endl; it = v3.begin(); for (; it != v3.end(); it++) { cout << *it << ", "; } cout << endl; /************************************************************************************************/ vector<int> v4(v3); // 定義時(shí)可以使用其他容器來(lái)初始化自己 cout << "v4里面的元素為:" << endl; it = v4.begin(); for (; it != v4.end(); it++) { cout << *it << ", "; } cout << endl; /************************************************************************************************/ vector<int> v5(v2.begin(), v2.end()); // 也可以使用該種方式將v2的元素全都賦值給自己 cout << "v5里面的元素為:" << endl; it = v5.begin(); for (; it != v5.end(); it++) { cout << *it << ", "; } cout << endl; /************************************************************************************************/ vector<int> v6(v2.begin() + 1, v2.end()); // begin返回來(lái)的就是一個(gè)指針迭代器,所以可以進(jìn)行加1操作,指向下一個(gè)元素 cout << "v6里面的元素為:" << endl; it = v6.begin(); for (; it != v6.end(); it++) { cout << *it << ", "; } cout << endl; /************************************************************************************************/ int text[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; vector<int> v7(text, text + 5); // 可以使用這種方式獲取數(shù)組的值初始化自己(1,2,3,4,5) cout << "v7里面的元素為:" << endl; it = v7.begin(); for (; it != v7.end(); it++) { cout << *it << ", "; } cout << endl; } // vector容器賦值assign玩法 void assign(void) { vector<int> v1(5); // 第一種玩法 會(huì)改變?cè)瓉?lái)vector中的元素內(nèi)存大小 v1.assign(3, 8); cout << "玩法一:" << endl; vector<int>::iterator it = v1.begin(); for (; it != v1.end(); it++) { cout << *it << ", "; } cout << endl; // 第二種玩法,使用迭代器賦值 vector<int> v2(10, 1); v1.assign(v2.begin(), v2.end()); cout << "玩法二:" << endl; it = v1.begin(); for (; it != v1.end(); it++) { cout << *it << ", "; } cout << endl; // 第三種玩法,使用指針賦值 int Array[5] = { 9, 8, 7, 6, 5 }; v1.assign(Array, Array + 2); cout << "玩法三:" << endl; it = v1.begin(); for (; it != v1.end(); it++) { cout << *it << ", "; } cout << endl; // 第四種玩法,使用賦值運(yùn)算符重載 vector<int> v3; v3 = v1; cout << "玩法四:" << endl; it = v3.begin(); for (; it != v3.end(); it++) { cout << *it << ", "; } cout << endl; } // resize將容器縮小和變大 與 empty判斷容器是否為空 void text3(void) { vector<int> v1(10); // 一、把容器元素縮小 cout << "v1的元素個(gè)數(shù):" << v1.size() << endl; v1.resize(5); // 調(diào)整他的元素個(gè)數(shù)為5 cout << "v1的元素個(gè)數(shù):" << v1.size() << endl; // 二、把容器擴(kuò)大時(shí),并給增加的元素賦值 v1.resize(8, 111); // 擴(kuò)充v1容器的大小為8,后續(xù)新增加的使用111賦值 cout << "v1的元素個(gè)數(shù):" << v1.size() << endl; cout << "v1的所有元素:"; for (int i = 0; i < v1.size(); i++) { cout << v1[i] << ", "; } cout << endl; // 三、把容器擴(kuò)大,不給增加的元素賦值 v1.resize(15); cout << "v1的元素個(gè)數(shù):" << v1.size() << endl; cout << "v1的所有元素:"; for (int i = 0; i < v1.size(); i++) { cout << v1[i] << ", "; } cout << endl; cout << endl << endl << "---empty---" << endl; // 判斷容器是否為空 vector<int> v2; if (v2.empty()) { cout << "v2為空!" << endl; } } // 尾部添加和刪除 void text4(void) { vector<int> v1; cout << "v1的元素個(gè)數(shù):" << v1.size() << endl; // 尾部添加一個(gè)元素 v1.push_back(666); cout << "v1的元素個(gè)數(shù):" << v1.size() << endl; // 尾部刪除一個(gè)元素 v1.pop_back(); cout << "v1的元素個(gè)數(shù):" << v1.size() << endl; } // at 與 front 與 back void text5(void) { vector<int> v1(10); // 可以使用at修改容器里面的值,返回的是一個(gè)引用 v1.at(0) = 888; // 和數(shù)組方式差不多 v1[1] = 999; // 輸出 cout << "v1的所有元素:"; for (int i = 0; i < v1.size(); i++) { cout << v1[i] << ", "; } cout << endl; // 也可以使用at輸出 cout << "v1的所有元素:"; for (int i = 0; i < v1.size(); i++) { cout << v1.at(i) << ", "; } cout << endl; // 他們返回的都是一個(gè)引用 cout << "第一個(gè)元素:" << v1.front() << endl; cout << "最后一個(gè)元素:" << v1.back() << endl; // 也可以使用他們賦值 v1.front() = 111; v1.back() = 222; cout << "v1的所有元素:"; for (int i = 0; i < v1.size(); i++) { cout << v1.at(i) << ", "; } cout << endl; } // insert 元素的插入 void text6(void) { vector<int> v1(10); // 往第一個(gè)元素的位置插入一個(gè)5 v1.insert(v1.begin(), 5); // 從第三個(gè)元素位置開(kāi)始插入5個(gè)222 v1.insert(v1.begin() + 2, 5, 222); vector<int> v2(3, 111); // 從第二個(gè)元素開(kāi)始插入v2的所有值 v1.insert(v1.begin() + 1, v2.begin(), v2.end()); cout << "v1的所有元素:"; for (int i = 0; i < v1.size(); i++) { cout << v1.at(i) << ", "; } cout << endl; } // 元素刪除 void text7(void) { vector<int> v1(10); // 刪除第一個(gè)元素 v1.erase(v1.begin()); // 刪除第一個(gè)到第三個(gè)元素 v1.erase(v1.begin(), v1.begin() + 3); // 刪除全部元素 v1.clear(); } int main(void) { //text1(); //text2(); //assign(); //text3(); //text4(); //text5(); //text6(); //text7(); system("pause"); return 0; }
注意:
vector容器常用的函數(shù)已經(jīng)列出來(lái)了,剩下還有很多個(gè)不常用的,就不說(shuō)明了,需要用到的話(huà),再另行百度吧!
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C++簡(jiǎn)明講解缺省參數(shù)與函數(shù)重載的用法
所謂缺省參數(shù),顧名思義,就是在聲明函數(shù)的某個(gè)參數(shù)的時(shí)候?yàn)橹付ㄒ粋€(gè)默認(rèn)值,在調(diào)用該函數(shù)的時(shí)候如果采用該默認(rèn)值,你就無(wú)須指定該參數(shù)。C++ 允許多個(gè)函數(shù)擁有相同的名字,只要它們的參數(shù)列表不同就可以,這就是函數(shù)的重載,借助重載,一個(gè)函數(shù)名可以有多種用途2022-06-06C語(yǔ)言中快速排序和插入排序優(yōu)化的實(shí)現(xiàn)
這篇文章主要介紹了C語(yǔ)言中快速排序和插入排序優(yōu)化的實(shí)現(xiàn),包括雙向劃分快速排序方法的介紹,需要的朋友可以參考下2015-11-11C++?雙向循環(huán)鏈表類(lèi)模版實(shí)例詳解
這篇文章主要為大家詳細(xì)介紹了C++?雙向循環(huán)鏈表類(lèi)模版實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-02-02C語(yǔ)言scanf,fscanf和sscanf的區(qū)別
每種語(yǔ)言都對(duì)正則表達(dá)式有著不同程度的支持,在C語(yǔ)言中,有輸入功能的這三個(gè)函數(shù)對(duì)正則表達(dá)式的支持并不強(qiáng)大,但是我們還是有必要了解一下2021-10-10Qt使用QListWidget實(shí)現(xiàn)自定義Item
這篇文章主要為大家詳細(xì)介紹了Qt如何使用QListWidget實(shí)現(xiàn)自定義Item的效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10