STL中的vector学习笔记

来源:互联网 发布:免费申请域名建立网站 编辑:程序博客网 时间:2024/05/12 10:08

vector是STL中的一种顺序性容器,类似于c语言中的数组,但是比普通数组的在空间的运用上更加的灵活。因为普通数组必须在定义是给定好大小,一旦在使用的过程中觉得空间大小不够用就不能够动态的增长了。vector它随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。

来看下它的空间组织结构:

这里写图片描述

数据结构定义如下:

template<class T, class Alloc = alloc>class vector{    ...    protected:        iterator start;             //表示目前使用空间的头        iterator finish;            //表示目前使用空间的尾        iterator end_of_storage;    //表示目前可用的尾    ...};

vector采用的迭代器是随机迭代器,由于其维护的是一个连续的线性空间,其迭代器执行的操作普通指针就可以完成。所以不难理解底层的vector的迭代器其实就是一普通的指针。
来看看vector迭代器的数据结构:

template <class T, class Alloc = alloc>class vector{public:    typedef T value_type;    typedef value_type* iterator;    ...};

vector有多个构造函数,默认的构造函数是构造一个初始长度为0的内存空间。继续向vector中添加元素的时候,如果超过当前的(capacity),则容量会扩充至两倍或者更大。那么问题来了~~~扩充空间是在原有的基础上呢还是重新申请一块空间呢??

答案是后者,vector会把扩充前的数据copy到新的内存空间上,并释放原有的内存空间。这样大动作的copy从效率角度看是很低的。这也是这种内存管理方式的一种缺点!!

有缺点就会有优点,vector的优点就是可进行随机访问支持[]操作符。(相比顺序性容器list)

来看看vector的一些基本操作:

#include<iostream>using namespace std;#include<vector>void main(){    vector<int> vec;    for (int i = 0; i < 10; i++)    {        vec.push_back(i); //尾部添加一个元素    }    //查看其当前元素的个数和当前分配的容量    cout << "vec.size()=" << vec.size() << "vec.capacity()=" << vec.capacity() << endl;    vec.pop_back();    //删除最后一个元素    cout<<"vec.back() = "<<vec.back()<<endl;   //查看当前最后一个元素    cout << "vec.front() = " << vec.front() << endl; //查看当前第一个元素    cout << "vec.at(4) = " << vec.at(4) << endl;  //返回下标为n的元素的引用,下标越界会抛出异常    cout << "vec[4] = " << vec[4] << endl;  //返回下标为n的元素的引用,n>=vec.size()则函数行为未定义    //迭代器遍历vector容器    vector<int>::iterator it;    for (it = vec.begin(); it != vec.end(); it++)    {        cout << *it << " ";    }    cout << endl;    cout << "vec.empty() : " << vec.empty() << endl;    //在第i+1个元素前面插入a    vec.insert(vec.begin() + 4, 100);    //清除第i+1个元素    vec.erase(vec.begin() + 4);    vec.erase(vec.begin(), vec.begin() + 3);//清除[first,last)中的所有元素    vec.resize(10); //调整vec的size大小    vec.resize(20, 1);    vec.reserve(100); //调整vec的capacity大小    vec.clear();  //清除当前所有元素    cout << vec.size() << "   " << vec.capacity() << endl;}

再来说说vector的细节问题:

  1. clear()函数是把vector的size清为零,相当于resize(0)。它只是把当前的元素的个数清零,元素在内存并没有消除,所以使用vector的过程中要注意,防止内存泄露。常用的办法是采用swap函数来替换并释放内存。
vector<int> vec;for(int i=0 ;i<10;i++){    vec.push_back(i);}vec.swap(vector<int>()); //将容量capacity也释放

2.vector中的reserve()函数和resize()函数的区别

resize()函数和容器的size息息相关,调用resize(n)后,容器的size为n。是否会影响capacity,取决于n的大小如果大于capacity,则会影响capacity的大小。

reserve()函数和容器的capacity息息相关,调用reserve(n)后:
- 若容器的capacity < n ,则重新分配内存空间,使得capacity等于n。
- 若容器的capacity >= n ,则capacity无变化。
-
从函数接口上看,resize()函数有两种,一种是一个参数,一种是两个参数。而reserve()函数只有一种,是一个参数。
从函数用途上看,容器调用resize()函数后,其空间被初始化,可以直接访问,但是reserve()函数预分配出去的空间没有被初始化,所以不可以访问。

3.vector的操作带来的迭代器失效问题

  • 向vector中添加元素后,且存储空间被重新分配,则指向容器的迭代器、指针和引用都会失效。若未重新分配空间,则插入位置之后的迭代器指针和引用将会失效。
  • 向vector中删除一个元素后,指向被删除元素之前的迭代器、引用和指针仍有效,之后的迭代器无效。
    vector迭代器失效图片