夏天/isummer

Sun of my life !Talk is cheap, Show me the code! 追风赶月莫停留,平芜尽处是春山~

博客园 首页 新随笔 联系 管理

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;
}

 

  程序输出:

  http://pic002.cnblogs.com/images/2012/426620/2012091215252725.jpg

 

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/

 

 

 

posted on 2015-12-18 22:40  夏天/isummer  阅读(523)  评论(0编辑  收藏  举报