C++ vector容器缩小capacity问题
作者:白白白白白kkk
C++ vector容器缩小capacity
vector容器是动态存储的,跟数组不同,定义vector的时候不需要声明容器的capacity。
首先说明一点,size是小于等于capacity的,一旦size超过了capacity,整个vector容器会“另辟居所”重新开辟更多的空间,这样也就造成了vector容器首地址发生改变。
下面是容器的size和capacity的关系:
#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容器会根据你传入的数据数量进行自动扩展,总是比你存入的数据多一些。
但是有一些时候我们不需要那么多开辟好的空间,对于数据size是确定的,这时候可以用匿名vector交换vector
先介绍一下vector的内置函数swap(),只贴核心代码了:
vector<int> v1; v1.reserve(10000);//预设一个空间大小 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()函数是预设一个大小,不会使其反复开辟,当然如果后续超过这个预设值,vector容器还是会自动开辟的。
上面的代码旨在展示swap()函数交换的是一整个容器,包含的是容器的capacity和数据的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);//匿名容器,用后自动销毁。除了没有自己的变量名,其他的一样 cout << "v1 capacity is " << v1.capacity() << endl;//3 cout << "v1 size is " << v1.size() << endl;//3 return 0; }
上面的代码可以看出:
一个vector如果是通过拷贝构造的,那么他的size和capacity相同,且等同于被拷贝的那个容器的size。
结合上面第二点的发现,swap函数是一整个交换的,这样理论上就可以用temp和v1换,最后使v1的size=capacity,节省了空间。另外,使用匿名容器更加高效方便。
C++ vector容器的常用用法
vector可以说是一个动态数组,它可以存储任何类型的数据,包括类!
使用vector需包含头文件 #include< vector >
.
一、不带参数
// 定义了一个int类型的容器 vector<int> v1; // 定义了一个double类型的容器 vector<double> v2;
注意事项:容器可以使用数组方式获取它的值 和 给它赋值,但是得注意越界!
例如:不可以使用数组方式给他赋值,因为容器并没有给他分配内容空间:
vector<int> v1; // 不可以使用数组方式给他赋值,因为容器并没有给他分配内容空间 v1[0] = 1; // error // 可以使用数组方式给他赋值: vector<int> v2(10); v2[0] = 1; // 正确 v2[11] = 11; // 错误,越界
二、带参数
1.定义了一个int类型的容器,定义时指定给他分配十个元素的空间
// 定义了一个int类型的容器,定义时指定给他分配十个元素的空间 vector<int> v1(10);
默认10个元素都是零值。
2.定义时指定10个元素的内存,同时给所有元素赋值666
vector<int> v3(10, 666);
3.定义时可以使用其他容器来初始化自己
vector<int> v1(5, 666); // 定义时可以使用其他容器来初始化自己 vector<int> v2(v1); // v1 和 v2 相等
4.// 也可以使用 返回迭代器 的方式将一个容器的元素全都赋值给自己
vector<int> v1(5, 666); vector<int> v2(v1.begin(), v1.end());
5.begin 和 end 返回来的就是一个指针迭代器,所以可以进行加减操作,指向其他元素的位置
vector<int> v1(5, 666); // 将v1的元素从第三个元素到最后的元素赋值给v2 vector<int> v2(v1.begin() + 2, v1.end());
6.可以使用数组来初始化容器
int Array[5] = {1, 2, 3, 4, 5}; // 将数组元素1,2,3,4给容器赋初值 vector<int> v1 = (Array, Array+3);
size 获取容器的元素个数
size()
vector<int> v1; v1.size();
capacity 获取容器的大小
capacity()
vector<int> v1;v1.capacity();
begin 获取容器第一个元素的迭代器
begin()
vector<int> v1(10, 666); v1.begin();
end 指向容器最后一个元素的下一个位置的迭代器
end()
vector<int> v1(10, 666); v1.end();
assign 赋值玩法
- 第一种玩法 会改变原来vector中的元素内存大小
将v1元素修改为5个,并且赋值888
vector<int> v1(10); v1.assign(5, 888); // 打印结果5个888
- 第二种玩法,使用迭代器赋值
将容器v2的10个1赋值给v1,使得v1和v2相等
vector<int> v1(5); vector<int> v2(10, 1); v1.assign(v2.begin(), v2.end()); // 打印结果10个1
- 第三种玩法,使用指针赋值
将数组的所有元素都赋值给v1
int Array[5] = { 9, 8, 7, 6, 5 }; vector<int> v1; v1.assign(Array, Array + 4); // 打印结果9,8,7,6,5
- 第四种玩法,使用赋值运算符重载
将v1所有元素赋值给v2
vector<int> v1(10, 1); vector<int> v2; v2 = v1; // 打印结果10个1
resize 将容器缩小和变大
一、把容器元素缩小
vector<int> v1(10); v1.resize(5); // 缩小长度为5
二、把容器扩大时,并给增加的元素赋值
vector<int> v1(5); v1.resize(8, 111); // 扩充v1容器的大小为8,后续新增加的使用111赋值
三、把容器扩大,不给增加的元素赋值
vector<int> v1(5); v1.resize(15);
empty 判断容器是否为空
为空返回true,为假返回false
vector<int> v1(5); if (v1.empty() == NULL) { cout << "v1为空!" << endl; }
push_back 尾部添加一个元素
vector<int> v1; v1.push_back(1); // 在尾部增加要给1
pop_back 尾部删除一个元素
vector<int> v1(10); v1.pop_back(); // 在尾部删除一个元素
at 和数组使用方式差不多
给第一个元素赋值1
vector<int> v1(10); v1.at(0) = 1;
打印输出容器里的所有元素
cout << "v1的所有元素:"; for (int i = 0; i < v1.size(); i++) { cout << v1.at(i) << ", "; }
front 获取容器的第一个元素
vector<int> v1(10); v1.front(); // 也可以使用他们赋值 v1.front() = 111; // 给第一个元素赋值111
back 获取容器的最后一个元素
vector<int> v1(10); v1.back(); // 也可以使用他们赋值 v1.back() = 222; // 给最后一个元素赋值222
insert 元素的插入
vector<int> v1(10); // 往第一个元素的位置插入一个5 v1.insert(v1.begin(), 5); // 从第三个元素位置开始插入5个222 v1.insert(v1.begin() + 2, 5, 222); vector<int> v2(3, 111); // 从第二个元素开始插入v2的所有值 v1.insert(v1.begin() + 1, v2.begin(), v2.end());
erase 与 clear 元素删除
vector<int> v1(10); // 删除第一个元素 v1.erase(v1.begin()); // 删除第一个到第三个元素 v1.erase(v1.begin(), v1.begin() + 3); // 删除全部元素 v1.clear();
汇总代码:
#include <iostream> #include <Windows.h> #include <vector> using namespace std; // 不带参数的 void text1(void) { vector<int> v1; cout << "v1的元素个数:"; cout << v1.size() << endl; cout << "v1容器的大小:"; cout << v1.capacity() << endl; v1.push_back(1); v1.push_back(2); cout << endl << "v1插入两个元素后:" << endl; cout << "v1的元素个数:"; cout << v1.size() << endl; cout << "v1容器的大小:"; cout << v1.capacity() << endl; /* 注意: 不可以使用数组方式给他赋值,因为容器并没有给他分配内容空间: vector<int> v; v[0] = 1; // error */ } // 带参数的 void text2(void) { vector<int> v2(10); // 定义时指定给他分配十个元素的空间 cout << "v2的元素个数:"; cout << v2.size() << endl; cout << "v2容器的大小:"; cout << v2.capacity() << endl; // 里面默认的值全为零 cout << "v2里面的元素为:" << endl; vector<int>::iterator it = v2.begin(); for (; it != v2.end(); it++) { cout << *it << ", "; } cout << endl; /* 可以使用数组方式给他赋值: 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); // 定义时指定10个元素的内存,同时给所有元素赋值666 cout << "v3里面的元素为:" << endl; it = v3.begin(); for (; it != v3.end(); it++) { cout << *it << ", "; } cout << endl; /************************************************************************************************/ vector<int> v4(v3); // 定义时可以使用其他容器来初始化自己 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返回来的就是一个指针迭代器,所以可以进行加1操作,指向下一个元素 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); // 可以使用这种方式获取数组的值初始化自己(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); // 第一种玩法 会改变原来vector中的元素内存大小 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; // 第四种玩法,使用赋值运算符重载 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的元素个数:" << v1.size() << endl; v1.resize(5); // 调整他的元素个数为5 cout << "v1的元素个数:" << v1.size() << endl; // 二、把容器扩大时,并给增加的元素赋值 v1.resize(8, 111); // 扩充v1容器的大小为8,后续新增加的使用111赋值 cout << "v1的元素个数:" << v1.size() << endl; cout << "v1的所有元素:"; for (int i = 0; i < v1.size(); i++) { cout << v1[i] << ", "; } cout << endl; // 三、把容器扩大,不给增加的元素赋值 v1.resize(15); cout << "v1的元素个数:" << 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的元素个数:" << v1.size() << endl; // 尾部添加一个元素 v1.push_back(666); cout << "v1的元素个数:" << v1.size() << endl; // 尾部删除一个元素 v1.pop_back(); cout << "v1的元素个数:" << v1.size() << endl; } // at 与 front 与 back void text5(void) { vector<int> v1(10); // 可以使用at修改容器里面的值,返回的是一个引用 v1.at(0) = 888; // 和数组方式差不多 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; // 他们返回的都是一个引用 cout << "第一个元素:" << v1.front() << endl; cout << "最后一个元素:" << 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); // 往第一个元素的位置插入一个5 v1.insert(v1.begin(), 5); // 从第三个元素位置开始插入5个222 v1.insert(v1.begin() + 2, 5, 222); vector<int> v2(3, 111); // 从第二个元素开始插入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); // 删除第一个元素 v1.erase(v1.begin()); // 删除第一个到第三个元素 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容器常用的函数已经列出来了,剩下还有很多个不常用的,就不说明了,需要用到的话,再另行百度吧!
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。