STL中的vector学习笔记

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迭代器失效图片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值