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