STL之vector

   vector是一种动态数组,是基本数组的类模板。其内部定义了很多基本操作。

  #include <vector> 注意:头文件没有“.h”

成员函数表:

函数

表述

assign(beg,end)

assign(n,elem)

将[beg; end)区间中的数据赋值给c。

将n个elem的拷贝赋值给c。

at(idx)

传回索引idx所指的数据,如果idx越界,抛出out_of_range。

back()

传回最后一个数据,不检查这个数据是否存在。

begin()

传回迭代器重的可一个数据。

capacity()

返回容器中数据个数。

clear()

移除容器中所有数据。

empty()

判断容器是否为空。

end()

指向迭代器中的最后一个数据地址。

erase(pos)

erase(beg,end)

删除pos位置的数据,传回下一个数据的位置。

删除[beg,end)区间的数据,传回下一个数据的位置。

front()

传回地一个数据。

get_allocator

使用构造函数返回一个拷贝。

insert(pos,elem)

insert(pos,n,elem)

insert(pos,beg,end)

在pos位置插入一个elem拷贝,传回新数据位置。

在pos位置插入n个elem数据。无返回值。

在pos位置插入在[beg,end)区间的数据。无返回值。

max_size()

返回容器中最大数据的数量。

pop_back()

删除最后一个数据。

push_back(elem)

在尾部加入一个数据。

rbegin()

传回一个逆向队列的第一个数据。

rend()

传回一个逆向队列的最后一个数据的下一个位置。

resize(num)

重新指定队列的长度。

reserve()

保留适当的容量。

size()

返回容器中实际数据的个数。

swap(c2)

swap(c1,c2)

将c1和c2元素互换。

同上操作。

vector<Elem> c

vector <Elem> c1(c2)

vector <Elem> c(n)

vector <Elem> c(n, elem)

vector <Elem> c(beg,end)

c.~ vector <Elem>()

创建一个空的vector。

复制一个vector。

创建一个vector,含有n个数据,数据均已缺省构造产生。

创建一个含有n个elem拷贝的vector。

创建一个以[beg;end)区间的vector。

销毁所有数据,释放内存。

实例:

//  作者:ychw365
//  测试 Vector 
#include "stdafx.h"
#include<iostream>   
#include <vector>
using   namespace   std;  

typedef vector<int> INTVECTOR;
INTVECTOR vector1; //初始化一个空向量
INTVECTOR vector2(5,2);//初始化4个2
INTVECTOR vector3(vector2.begin(),vector2.begin()+3);
//初始化vector
void InitVector()
{
	/*vector1.push_back(1);
	vector1.push_back(3);
	vector1.push_back(5);
	vector1.push_back(7);
	vector1.push_back(9);
	vector1.push_back(11);*/
	int ia[] = {1,3,5,7,9,11,13,15};  
	vector1.resize(8);   
	copy(ia, ia+8, vector1.begin());

}

//输出向量
void ShowVector(INTVECTOR & vectorTemp)
{

	cout<<"容器容量:"<<vectorTemp.capacity()<<endl;
	cout <<"容器元素:"<<vectorTemp.size() << endl;   
    INTVECTOR::const_iterator  cIter;

	for(cIter=vectorTemp.begin();cIter!=vectorTemp.end();cIter++)
	{
       cout<<*cIter<<" ";
	}
	cout <<endl;

}
/*  构造函数测试 
    

1.vector<elementType> vecList; 创建一个没有任何元素的空向量vecList(使用默认构造函数) 
2.vector<elementType> vecList(otherVecList)    创建一个向量vecList,并使用向量otherVecList中的元素初始化该向量。向量vecList与向量otherVecList的类型相同 
3.vector<elementType> vecLIst(size);  创建一个大小为size的向量vecList,并使用默认构造函数初始化该向量 
4.vector<elementType> vecList(n,elem);  创建一个大小为n的向量vecList,该向量中所有的n个元素都初始化为elem 
5.vector<elementType> vecList(begin,end);   创建一个向量vecList,并初始化该向量(begin,end)中的元素。即,从begin到end-1之间的所有元素 

*/
void constructor_test()
{   
	//1.如果vector1
    INTVECTOR vector4(vector2);//2
	INTVECTOR  vector5(3);//3 
	 //4.如vector2
	INTVECTOR vector6(++vector2.begin(),--vector2.end());//5
    
	ShowVector(vector1);
	ShowVector(vector2);
	ShowVector(vector3);
	ShowVector(vector4);
	ShowVector(vector5);
	ShowVector(vector6);
}
//分配元素
void assign_test()
{
	vector2.assign(7,3);
	ShowVector(vector2);

	INTVECTOR::iterator vIter=vector2.begin();;
	vIter+=3;
	vector1.assign(vIter,vector2.end());
	ShowVector(vector1);
}
//返回指定位置元素
//1.reference at( size_type _Pos);
//2. const_reference at(size_type _Pos) const;
void at_test()
{

	ShowVector(vector1);

   // int i=vector1.at(0);  //1
	//const int j=vector1.at(1);//2
	int &i=vector1.at(0);  //1
	const int &j=vector1.at(1);//2
	cout << "The first element is " << i << endl;
    cout << "The second element is " << j << endl;


}
//返回最后一个元素
//reference back( ); 
//const_reference back( ) const;
void back_test()
{ 
   ShowVector(vector1);
   int &i=vector1.back();//1
   const int& ii = vector1.back();//2
   cout << "The last integer of vector1 is " << i << endl;
   cout << "TThe last integer of vector1  is "<< ii << endl;

}

//返回第一个一个元素
//reference front( ); 
//const_reference front( ) const;
void front_test()
{ 
   ShowVector(vector1);
   int &i=vector1.front();//1
   const int& ii = vector1.front();//2
   cout << "The frist integer of vector1 is " << i << endl;
   cout << "TThe frist integer of vector1  is "<< ii << endl;

}

//操作符[]
// reference operator[]( size_type _Pos);
// const_reference operator[](size_type _Pos) const;
void  operator_test1()
{
   	ShowVector(vector1);
	int &i=vector1[0];  //1
	const int &j=vector1[1];//2
	cout << "The first element is " << i << endl;
    cout << "The second element is " << j << endl;

}
//容量
//size_type capacity( ) const;
/*
	size是指容器当前拥有元素的个数,而capacity是指容器在必须分配新的存储空间之前可以存放的元素总数。
	如vector<int> ivect(10),ivect.capacity()=10,ivect.size()=0,当你向ivect中插入元素时,只要没有超过十个,
	那么capacity就不变,而size为你插入的元素的个数。当你插入第十个时,capacity=size=10,当再插入一个,
	即第十一个数据时,容器重新分配存储空间:ivect.capacity()=20,而ivect.size()=11,即容器重新分配空间的话是现有空间的2倍进行分配,
	以保证vector的效率。
*/
  void   capacity_test()
  {
    ShowVector(vector2); 
	vector2.push_back(1);
    cout<<"增加1个元素"<<endl;
    cout<<"容器容量:"<<vector2.capacity()<<endl;
	cout <<"容器元素:"<<vector2.size() << endl;   
  }
  //移除容器中所有数据。

  void clear_test()
  {
   ShowVector(vector1);
   vector1.clear( );
   cout<<"清除"<<endl;
   cout << "The size of vector1 after clearing is " << vector1.size( ) << endl;
   cout << "The capacity of vector1 after clearing is " << vector1.capacity() << endl;

  }
//判断容器是否为空。
  void empty_test()
  {
	     if ( vector1.empty( ) )
      cout << "The vector is empty." << endl;
         else
      cout << "The vector is not empty." << endl;
		 vector1.clear();
		 cout<<"清除"<<endl;
	 	     if ( vector1.empty( ) )
      cout << "The vector is empty." << endl;
         else
      cout << "The vector is not empty." << endl;

  }
 //e指向迭代器中的第一个数据地址。
  void begin_test()
  {   
      ShowVector(vector1);
	  INTVECTOR::iterator VIter=vector1.begin();
	 // INTVECTOR::const_iterator VIter=vector1.begin();

	  cout<<"第一个:"<<*VIter<<endl;
	  VIter++;
	  cout<<"下一个:"<<*VIter<<endl;

  }
//指向迭代器中的最后一个数据地址。
  void end_test()
  {
	  ShowVector(vector1);
	  INTVECTOR::iterator VIter=vector1.end();// 注意是:最后一个元素的下一位置的指针
	  // INTVECTOR::const_iterator VIter=vector1.end();
	   cout<<"最后一个:"<<*(--VIter)<<endl; 
	  VIter--;
	  cout<<"前一个:"<<*VIter<<endl;

  }
//erase(pos)  删除pos位置的数据,传回下一个数据的位置。
//erase(beg,end) 删除[beg,end)区间的数据,传回下一个数据的位置。 
  void erase_test()
  {
	   ShowVector(vector1);
	   INTVECTOR::iterator vIter;
	   vIter=vector1.erase(vector1.begin());
	   cout<<"删除第一个"<< endl;
	   cout<<"下一个数据:"<< *vIter <<endl;
	   ShowVector(vector1);
	   vector1.erase(++vector1.begin(),--vector1.end());
	   cout<<"删除第二到倒数第二数据"<<endl;
	    ShowVector(vector1);

  }
//insert(pos,elem)  在pos位置插入一个elem拷贝,传回新数据位置。
//insert(pos,n,elem) 在pos位置插入n个elem数据。无返回值。
//insert(pos,beg,end)在pos位置插入在[beg,end)区间的数据。无返回值。
void insert_test()
{   
	ShowVector(vector1);
	vector1.insert(vector1.begin(),1);
	ShowVector(vector1);
    vector1.insert(vector1.begin(),3,1);
	ShowVector(vector1);
	vector1.insert(vector1.begin(),vector2.begin(),vector2.end());
	ShowVector(vector1);


}
// 返回容器中最大数据的数量。
void max_size_test()
{
   INTVECTOR::size_type i;
   i = vector1.max_size( );   
   cout << "The maximum possible length of the vector is " << i << "." << endl;

}
//删除最后一个数据。
void pop_back_test()
{
   ShowVector(vector1);
   vector1.pop_back();
   ShowVector(vector1);
}
//在尾部加入一个数据。
void push_back_test()
{
   ShowVector(vector1);
   vector1.push_back(1);
   ShowVector(vector1);
}

//传回一个逆向队列的第一个数据。
void rbegin_test()
{
	 ShowVector(vector1);
	INTVECTOR::reverse_iterator reverseIter;
	reverseIter=vector1.rbegin();
	cout<<"逆向队列第一个"<<*reverseIter<<endl;
}
//传回一个逆向队列的第一个数据。
void rend_test()
{
	 ShowVector(vector1);
	INTVECTOR::reverse_iterator reverseIter;
	reverseIter=vector1.rend();
	cout<<"逆向队列最后一个"<<*(--reverseIter)<<endl; //也是最后一个下一个
}
//reserve()保留适当的容量。
void reserve_test()
{
	  ShowVector(vector1);
	  vector1.reserve(20);
	   ShowVector(vector1);
}
//resize(num) 重新指定队列的长度。 
//void resize( size_type _Newsize,Type _Val);
 void resize_test()
 { 
	 ShowVector(vector1);
	 vector1.resize(20);
	 ShowVector(vector1);
	 vector1.resize(30,2);//利用2填充位置
	 ShowVector(vector1);
 }
 //交换
 void swap_test()
 {
	 ShowVector(vector1);
	 ShowVector(vector2);
	 vector1.swap(vector2);
	 cout<<"交换后:"<<endl;
	 ShowVector(vector1);
	 ShowVector(vector2);

 }


int main()
{
	InitVector();
    //ShowVector(vector2);
	//constructor_test();
	//assign_test();
	//at_test();
	 //back_test();
	//front_test();
	//operator_test1();
	//capacity_test();
	//clear_test();
	//empty_test();
	//begin_test();
	//end_test();
	//erase_test();
	//insert_test();
	//max_size_test();
	//pop_back_test();
	//push_back_test();
    //rbegin_test();
    //rend_test();
	//reserve_test();
	//resize_test();
	swap_test();
	getchar();
	return 0;
}


 vector 使用find

#include "stdafx.h"
#include <vector>
#include <algorithm>
#include <string> 
   
 struct value_t 
{ 
    int a; 
     int b; 
  }; 
   
  class vector_finder 
 { 
 public: 
     vector_finder(const int a):m_i_a(a){} 
     bool operator ()(const std::vector<struct value_t>::value_type &value) 
    { 
         return value.a == m_i_a;
	  } 
	 
  private: 
      int m_i_a;                     
  }; 
   
   
  int main() 
  { 
      std::vector<struct value_t> my_vector; 
      struct value_t my_value; 
     
     my_value.a = 11; my_value.b = 1000; 
      my_vector.push_back(my_value); 
       
     my_value.a = 12; my_value.b = 1001; 
     my_vector.push_back(my_value); 
    
     my_value.a = 13; my_value.b = 1000; 
     my_vector.push_back(my_value); 
  
     my_value.a = 14; my_value.b = 1000; 
     my_vector.push_back(my_value); 

	  my_value.a = 12; my_value.b = 1003; 
     my_vector.push_back(my_value); 
       
      std::vector<struct value_t>::iterator it = my_vector.end(); 
      it = std::find_if(my_vector.begin(), my_vector.end(), vector_finder(12)); 
     if (it == my_vector.end()) 
         printf("not found\n");        
    else 
         printf("found value.a:%d value.b:%d\n", it->a, it->b); 
         
     getchar(); 
      return 0;         
  } 


 

Vector使用常见问题

1)迭代器失效
iterator失效主要有两种情况:
a.iterator变量已经变成了“悬空指针”,对它进行*,++,--都会引起程序内存操作异常;
b.iterator所指向的变量已经不是你所以为的那个变量了。

vector迭代器的几种失效的情况:
a.当插入(push_back)一个元素后,end操作返回的迭代器肯定失效。
b.当插入(push_back)一个元素后,capacity返回值与没有插入元素之前相比有改变,则需要重新加载整个容器,此时first和end操作返回的迭代器都会失效。
c.当进行删除操作(erase,pop_back)后,指向删除点的迭代器全部失效;指向删除点后面的元素的迭代器也将全部失效。

 

比较常见的一种场景是遍历一个vector,删除符合条件的数据,正确的写法如下:

vector<int> myvector;
for(vector<int>::iterator iter=myvector.begin();iter!=myvector.end();)
{
    if(10 == (*iter))
        iter=myvector.erase(iter);
    else
        ++iter;
} 


在erase之后,删除的迭代器之后的数据前移,因此,在删除之后,不需要对迭代器++


 

2)元素访问
vector支持随机内存访问,我们可以使用at和[]来访问元素,这两者有什么区别呢?
在不越界的情况下,两者没有区别;在越界的情况下,at会抛出一个std::out_of_range异常。而C++98标准说[]可以、但不一定要进行下标越界检查。因此,标准库实现方可以自由选择是否为operator[]加上下标越界检查功能。

 

vector<int> myvector;
myvector.reserve(10);
try
{
    cout << myvector.at(100);
}
catch(...)
{
    cout << "got you" << endl;
} 

输出异常  got you
 

vector<int> myvector;
myvector.reserve(10);
 
try
{
    cout << myvector[100];
}
catch(...)
{
    cout << "got you" << endl;
} 

崩溃

3)拷贝构造函数
初学者使用vector使用常常会遇到的一个麻烦就是忘记定义拷贝构造函数。向上代码,看什么时候我们需要拷贝构造函数

 

class A  
{  
public:  
    A(){cout << "construct" << endl;}  
    ~A(){cout << "deconstruct" << endl;}  
    A(const A&){cout << "copy construct" << endl;}  
};  
   
void push_vec(vector<A>& myvector)  
{     
    A a;  
    myvector.push_back(a);  
    cout << "my vector capacity:" << myvector.capacity() << endl;  
}  
   
void fun()  
{  
    vector<A> myvector;  
   
    cout << "---begin----"<<endl;  
    push_vec(myvector);  
    cout << "---end----"<<endl;  
   
    cout << "---begin----"<<endl;  
    push_vec(myvector);  
    cout << "---end----"<<endl;  
   
    cout << "---begin----"<<endl;  
    push_vec(myvector);  
    cout << "---end----"<<endl;  
   
    cout << "---begin----"<<endl;  
    push_vec(myvector);  
    cout << "---end----"<<endl;  
   
}  
   
int _tmain(int argc, _TCHAR* argv[])  
{  
    fun();  
   
    system("pause");  
    return 0;  
} 

 

输出:

---begin----
construct
copy construct
my vector capacity:1
deconstruct
---end----
---begin----
construct
copy construct
deconstruct
copy construct
my vector capacity:2
deconstruct
---end----
---begin----
construct
copy construct
copy construct
deconstruct
deconstruct
copy construct
my vector capacity:3
deconstruct
---end----
---begin----
construct
copy construct
copy construct
copy construct
deconstruct
deconstruct
deconstruct
copy construct
my vector capacity:4
deconstruct
---end----
deconstruct
deconstruct
deconstruct
deconstruct

分析:
第一个push_vec(myvector),输出:
construct // A a
copy construct // myvector.push_back(a);调用拷贝构造函数
my vector capacity:1
deconstruct // a的生命周期到,析构

第2个push_vec(myvector),输出:
construct // A a
copy construct // myvector.push_back(a); 此时capacity不够大,需要重新分配内存,先将第一次push的a调用拷贝构造函数拷贝到新的内存,
deconstruct // 析构掉第一次push的a(原有内存)
copy construct //将第2个a 调用拷贝构造函数push到vector新申请的内存中
my vector capacity:2
deconstruct // a的生命周期到,析构


4)释放内存

vector在调用erase,pop_back删除元素的时候,并不会释放内存,因此,在vector生命期内,需要释放vector所占用内存的时候,可以使用如下代码:

template < class T >
void ClearVector( vector< T >& vt )
{
vector< T > vtTemp;
veTemp.swap( vt );
}



如果需要部分释放,可以先将vector的数据拷贝到另一个vector,然后调用swap。

5. 结语
vector具有很多优秀的特点:随机访问、动态扩张、额外消耗少,非常适合多查询的应用场景。但是,由于其需要保持内存连续,在删除某个元素之后,后续元素需要拷贝前移,这会带来一些消耗,因此不适合随机删除的场景。


 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值