目录
0.引言
1.构造函数
2. 赋值函数
3. vector 容量与大小
4. vector 插入和删除
5. vector 元素访问与更改
6. vector 互换
9. vector 预留空间
0.引言
这篇博客将详细介绍 vector,由于总体上与上一篇介绍的 string 类似,在此处注意展示其使用。关于 vector 有如下特点:
(1). vector是表示可变大小数组的序列容器。
(2). 像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
(3). vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小 为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
(4). vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是 对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增 长。
(5). 与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list 统一的迭代器和引用更好。
在 STL 中,vector 的操作有一下常用的函数,接下来我们将对其进行详细介绍:
1. vector<T> v; //T表示数据的类型,可以是int类型,也可以是string对象。
2. vector(v.begin(), v,end()); //将v[begin().end())区间(前闭后开)中的元素拷贝给本身。
3. vector(n, elem); //构造函数将n个elem拷贝给本身。
4. vector(const vector &vec); //拷贝构造函数。
5. vector& operator=(const vector &vec); //重载=操作符。
6. assign(begin,end); //将[begin,end)区间中的数据拷贝赋值给本身。
7. assign(n,elem); //将n个elem拷贝赋值给本身。
8. empty(); //判断容器是否为空。
9. capacity(); //容器的容量。
10. size(); //返回容器中元素的个数。
11. resize(int num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
12. resize(int num, elem); //重新指定容器的长度为num,若容器变成,则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
13. push_back(ele); //尾部插入元素ele。
14. pop_back(); //删除最后一个元素。
15. insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele。
16. insert(const_iterator pos, int count ele); //迭代器指向位置pos插入count个元素。
17. erase(const_iterator pos); //删除迭代器指向的元素。
18. erase(cons_titerator start, const_iterator end); //删除迭代器从start到end之间的元素。
19. clear(); //删除容器中所有元素。
20. at(int idx); ///返回索引为idx所指的数据。
21. operator[]; //返回索引idx所指的数据。
22. front(); //返回容器中第一个数据元素。
23. back(); //返回容器中最后一个数据元素。
24. swap(vec); //将vec与本身的元素互换。
25. reserve(int len); //容器预留len个元素长度,预留位置不初始化,元素不可访问。
1.构造函数
构造函数包括如下:
1. vector<T> v; //T表示数据的类型,可以是int类型,也可以是string对象
2. vector(v.begin(), v,end()); //将v[begin().end())区间(前闭后开)中的元素拷贝给本身。
3. vector(n, elem); //构造函数将n个elem拷贝给本身
4. vector(const vector &vec); //拷贝构造函数
void print(vector<int> v)//迭代器访问打印数据
{
vector<int>::iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
it++;
}
cout << endl;
}
vector<int> v1;//默认构造,无参创建v1对象
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
print(v1);
vector<int> v2(v1.begin(), v1.end());//区间构造v2
print(v2);
vector<int> v3(10,1); //n个elem构造:此处10个1
print(v3);
vector<int> v4(v3); //拷贝构造
print(v4);
2. 赋值函数
赋值函数包括:
1. vector& operator=(const vector &vec); //重载等号操作符。
2. assign(begin,end); //将[begin,end)区间中的数据拷贝赋值给本身。
3. assign(n,elem); //将n个elem拷贝赋值给本身。
我们知道利用 = 重载赋值是最简单的。
vector<int> v1;//默认构造,无参创建v1对象
for (int i = 0; i < 10; i++)
v1.push_back(i);//尾插
print(v1);
vector<int> v2 = v1;
print(v2);
vector<int> v3;
v3.assign(v1.begin(), v1.end());
print(v3);
vector<int> v4;
v4.assign(10,1);
print(v4);
3. vector 容量与大小
函数包括:
1. empty(); //判断容器是否为空
2. capacity(); //容器的容量
3. size(); //返回容器中元素的个数
4. resize(int num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
5. resize(int num, elem); //重新指定容器的长度为num,若容器变成,则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
需要注意的是:
(1). capacity表示在不分配更多内存的情况下,容器可以保存的最多元素个数。size 指的是它实际所包含的元素个数。
(2). vector 容器的大小不能超出它的容量,在大小等于容量的基础上,只要增加一个元素,就必须分配更多的内存。此时 vector 往往会申请多个存储空间。
(3). 一旦 vector 容器的内存被重新分配,则和 vector 容器中元素相关的所有引用、指针以及迭代器,都可能会失效,最稳妥的方法就是重新生成。
vector<int> v1;//默认构造,无参创建v1对象
for (int i = 0; i < 10; i++)
v1.push_back(i);//尾插
print(v1);
cout << "容量:" << v1.capacity() << endl;
cout << "大小:" << v1.size() << endl;
v1.resize(20); //如果重新指定的比原来长了,默认用0填充新的位置
print(v1);
v1.resize(40,10); //如果重新指定的比原来长了,也可给定值填充新的位置
print(v1);
v1.resize(5); //如果重新指定的比原来短了,超出的部分会删除掉
print(v1);
v1.resize(0);
if (v1.empty())
cout << "容量为空" << endl;
4. vector 插入和删除
1. push_back(ele); //尾部插入元素ele
2. pop_back(); //删除最后一个元素
3. insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele
4. insert(const_iterator pos, int count, ele); //迭代器指向位置pos插入count个元素
5. erase(const_iterator pos); //删除迭代器指向的元素
6. erase(cons_titerator start, const_iterator end); //删除迭代器从start到end之间的元素
7. clear(); //删除容器中所有元素
vector<int> v1;//默认构造,无参创建v1对象
for (int i = 0; i < 10; i++)
v1.push_back(i);//尾插
print(v1);
v1.pop_back();
v1.pop_back();//尾删
print(v1);
v1.insert(v1.begin(),100);//在指定位置插入数据,此处为begin
print(v1);
v1.insert(v1.begin(),2,200);//在指定位置插入数据n个元素,此处为begin,两个200
print(v1);
v1.erase(v1.begin()++);//删除第二个位置
print(v1);
v1.erase(v1.begin(),v1.end());//删除指定区间
print(v1);
v1.clear();//清空v1
print(v1);
5. vector 元素访问与更改
1. at(int idx); ///返回索引为idx所指的数据。
2. operator[]; //返回索引idx所指的数据。
3. front(); //返回容器中第一个数据元素
4. back(); //返回容器中最后一个数据元素。
vector<int> v1;//默认构造,无参创建v1对象
for (int i = 0; i < 10; i++)
v1.push_back(i);//尾插
for (int i = 0; i < 10; i++)
cout << v1.at(i) << " ";
cout << endl;
cout << "第一个元素:" << v1.front() << endl;
cout << "最后一个元素:" << v1.back() << endl;
for (int i = 0; i < 10; i++)
cout << v1[i]*2 << " ";//[ ]最简单的访问数据方式
cout << endl;
6. vector 互换
实现两个容器内元素进行互换所调用的函数。
1. swap(vec); //将vec与本身的元素互换
cout << "交换前:"<< endl;
vector<int> v1;//默认构造,无参创建v1对象
for (int i = 0; i < 10; i++)
v1.push_back(i);//尾插
print(v1);
vector<int> v2;//默认构造,无参创建v1对象
for (int i = 10; i < 20; i++)
v2.push_back(i);//尾插
print(v2);
cout << "交换后:" << endl;
v1.swap(v2);
print(v1);
print(v2);
巧用 swap 可以收缩内存空间
vector<int>v;
for (int i = 0; i < 100000; i++)
{
v.push_back(i);
}
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
v.resize(3); //重新指定大小
cout << "v的容量为:" << v.capacity() << endl; //resize操作,容量并没有变,多余的容量浪费了
cout << "v的大小为:" << v.size() << endl;
//巧用swap收缩内存
vector<int>(v).swap(v);
//vector<int>(v)创建了一个为匿名对象,
//会按v的大小初始化这个匿名对象容器的大小
//swap(v)会对匿名对象容器与原容器做一个交换,
//则原容器的指针指向匿名对象的容器,匿名对象的容器的指针改为指向原容器
//系统运行完创建匿名函数这一句语句后对匿名对象的指针(即地址、内存)进行回收
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
9. vector 预留空间
目的是为了减少vector在动态扩展容量时的扩展次数,提高程序运行效率。
1. reserve(int len); //容器预留len个元素长度,预留位置不初始化,元素不可访问。
vector<int>v1;
int num1 = 0; //统计开辟次数
int* p = NULL;
for (int i = 0; i < 1000000; i++)
{
v1.push_back(i);
if (p != &v1[0]) //一开始指针不指向容量首地址,所以让指针指向容量首地址,开辟内存次数加1
{
p = &v1[0];
num1++; //由于容量不够,会再次开辟一段容量更大的内存空间,原小容量的内存空间被释放
}
}
cout << "num1:" << num1 << endl;
vector<int>v2;
//预留空间
v2.reserve(1000000);
int num2 = 0; //统计开辟次数
* p = NULL;
for (int i = 0; i < 1000000; i++)
{
v2.push_back(i);
if (p != &v2[0])
{
p = &v2[0];
num2++;
}
}
cout << "num2(reserve):" << num2 << endl;
vector 与 string STL接口大多是一样的,学会一个另一个的学习也会更加的轻松。