STL中的Vector相关用法
标准库vector类型使用需要的头文件:#include <vector>。
vector 是一个类模板,不是一种数据类型,vector<int>是一种数据类型。
Vector的存储空间是连续的,list不是连续存储的。
1. 定义和初始化
vector< typeName > v1; //默认v1为空,故下面的赋值是错误的v1[0]=5;
//v2是v1的一个副本,若v1.size()>v2.size()则赋值后v2.size()被扩充为 v1.size()。 vector<typeName>v2(v1); 或v2=v1;或vector<typeName> v2(v1.begin(), v1.end());
vector< typeName > v3(n,i);//v3包含n个值为i的typeName类型元素 vector< typeName > v4(n); //v4含有n个值为0的元素 int a[4]={0,1,2,3,3}; vector<int> v5(a,a+5);//v5的size为5,v5被初始化为a的5个值。后一个指针要指向将被拷贝的末元素的下一位置。 vector<int> v6(v5);//v6是v5的拷贝 vector< 类型 > 标识符(最大容量,初始所有值);
2. 值初始化
(1)如果没有指定元素初始化式,标准库自行提供一个初始化值进行值初始化。
(2)如果保存的式含有构造函数的类类型的元素,标准库使用该类型的构造函数初始化。
(3)如果保存的式没有构造函数的类类型的元素,标准库产生一个带初始值的对象,使用这个对象进行值初始化。
3. vector对象最重要的几种操作
(1)v.push_back(t) 在容器的最后添加一个值为t的数据,容器的size变大。
其中,采用的是复制构造函数重新建立这样的一个对象。 另外list有push_front()函数,在前端插入,后面的元素下标依次增大。
(2)v.size() 返回容器中数据的个数,size返回相应vector类定义的size_type的值。
v.resize(2*v.size)或v.resize(2*v.size, 99) 将v的容量翻倍(并把新元素的值初始化为99)
(3)v.empty() 判断vector是否为空
(4)v[n] 返回v中位置为n的元素
(5)v.insert(pointer,number, content) 向v中pointer指向的位置插入number个content的内容。
还有v. insert(pointer, content),v.insert(pointer,a[2],a[4])将a[2]到a[4]三个元素插入。
(6) v.pop_back() 删除容器的末元素,并不返回该元素。
(7)v.erase(pointer1,pointer2) 删除pointer1到pointer2中间(包括pointer1所指)的元素。
vector中删除一个元素后,此位置以后的元素都需要往前移动一个位置,虽然当前迭代器位置没有自动加1,
但是由于后续元素的顺次前移,也就相当于迭代器的自动指向下一个位置一样。
(8)v1==v2 判断v1与v2是否相等。
(9)!=、<、<=、>、>= 保持这些操作符惯有含义。
(10)vector<typeName>::iterator p=v1.begin( ); p初始值指向v1的第一个元素。*p取所指向元素的值。
对于const vector<typeName>只能用vector<typeName>::const_iterator类型的指针访问。
(11)p=v1.end( ); p指向v1的最后一个元素的下一位置。
(12)v.clear() 删除容器中的所有元素。但是内存空间不变,只是情况所在内容。
(13)v.reserve() 初始化预留空间,此动作可以与对象定义分开。
(14)
3. vector的assign()用法
vector::assign //用来构造一个vector的函数,类似于copy函数
void assign( size_type _Count, const Type& _Val);
注意:
(1)_Count指要构造的vector成员的个数, _Val指成员的数值,他的类型必须与vector类型一致!
(2)这个函数用来,在创建Vector对象后,但是没有对其进行构造容器元素,即将创建对象与构造扩展数据分开。
template<class InputIterator> void assign( InputIterator _First, InputIterator _Last ); //两个指针,分别指向复制开始和结束的地方! EXAMPLE // vector_assign.cpp // compile with: /EHsc #include <vector> #include <iostream> int main( ) { using namespace std; vector<int> v1, v2, v3; vector<int>::iterator iter; v1.push_back(10); v1.push_back(20); v1.push_back(30); v1.push_back(40); v1.push_back(50); cout << "v1 = " ; for (iter = v1.begin(); iter != v1.end(); iter++) cout << *iter << " "; cout << endl; v2.assign(v1.begin(), v1.end()); cout << "v2 = "; for (iter = v2.begin(); iter != v2.end(); iter++) cout << *iter << " "; cout << endl; v3.assign(7, 4) ; cout << "v3 = "; for (iter = v3.begin(); iter != v3.end(); iter++) cout << *iter << " "; cout << endl; }
输出:
v1 = 10 20 30 40 50 v2 = 10 20 30 40 50 v3 = 4 4 4 4 4 4 4
size()成员指当前拥有的元素个数;capacity()成员指当前(容器必须分配新存储空间之前)可以存储的元素个数。reserve()成员可以用来控制容器的预留空间。vector另外一个特性在于它的内存空间会自增长,每当vector容器不得不分配新的存储空间时,会以加倍当前容量的分配策略实现重新分配。例如,当前capacity为50,当添加第51个元素时,预留空间不够用了,vector容器会重新分配大小为100的内存空间,作为新连续存储的位置。
在调用push_back时,每次执行push_back操作,相当于底层的数组判定是否需要重新分配大小;,然后将原来的元素拷贝到新的存储,之后在拷贝push_back的元素,最后要析构原有 的vector并释放原有的内存。例如下面程序:
#include <iostream> #include <cstdlib> #include <vector> using namespace std; class Point { public: Point() { cout << "construction" << endl; } Point(const Point& p) { cout << "copy construction" << endl; } ~Point() { cout << "destruction" << endl; } }; int main() { vector<Point> pointVec; Point a; Point b; pointVec.push_back(a); pointVec.push_back(b); cout<<pointVec.size()<<std::endl; return 0; }
程序输出:
4. vector的内存释放
由于vector的内存占用空间只增不减,比如你首先分配了10,000个字节,然后 erase掉后面9,999个,留下一个有效元素,但是内存占用仍为10,000个。所有内存空间是在vector析构时候才能被系统回收。 empty()用来检测容器是否为空的,clear()可以清空所有元素。但是即使clear(),vector所占用的内存空间依然如故,无法保证内存 的回收。
(1) 如果需要空间动态缩小,可以考虑使用deque。如果非vector不可,可以用swap()来帮助你释放内存。具体方法如下:
vector<int> nums; nums.push_back(1); nums.push_back(1); nums.push_back(2); nums.push_back(2); vector<int>().swap(nums); //或者nums.swap(vector<int> ())
或者如下所示,使用一对大括号,意思一样的:
//加一对大括号是可以让tmp退出{}的时候自动析构 { std::vector<int> tmp = nums; nums.swap(tmp); }
swap()是交换函数,使vector离开其自身的作用域,从而强制释放vector所占的内存空间,总而言之,释放vector内存最简单的方法是 vector<int>.swap(nums)。
(2)但是如果nums是一个类的成员,不能把 vector<int>.swap(nums)写进类的析构函数中,否则会导致double free or corruption (fasttop)的错误,原因可能是重复释放内存。标准解决方法如下:
template < class T > void ClearVector( vector< T >& vt ) { vector< T > vtTemp; veTemp.swap( vt ); }
(3) 如果Vector中存放的是指针
如果vector中存放的是指针,那么当vector销毁时,这些指针指向的对象不会被销毁,那么内存就不会被释放。如下面这种情况,vector中的元素时由new操作动态申请出来的对象指针:
#include <vector> using namespace std; vector<void *> v;
每次new之后调用v.push_back()该指针,在程序退出或者根据需要,用以下代码进行内存的释放:
for (vector<void *>::iterator it = v.begin(); it != v.end(); it ++) if (NULL != *it) { delete *it; *it = NULL; } v.clear();
官方说明: http://www.cplusplus.com/reference/vector/vector/assign/