STL 源码剖析之Vector

1. Vector 概念

作为STL中常用的序列式容器,vector的数据安排与操作方式,与array都十分相似,它们唯一的差别是对于空间运用的灵活性。array称为静态数组,一旦初始化则不能改变大小,而vector称为动态数组,随着元素的不断加入,它的内部机制会自行扩充空间。因此,vector的实现技术,关键在于其对空间大小的控制以及重新配置时的数据移动效率。

2. Vector 定义

为了简单起见,Vector底层实现代码中均省略空间配置器等接口的描述。Vector底层所采用的数据结构非常简单:线性连续空间,并且运用三个指针进行一系列操作。

如下图所示,Vector新增元素时,如果超过当时的容量,则容量会扩充至两倍或者更大空间(重新配置、移动数据、释放原空间)。

2.1. Vector嵌套型别定义

typedef T           value_type;         // 泛型定义
typedef value_type* pointer;            // 原生指针
typedef value_type* iterator;           // 迭代器
typedef value_type& reference;          // 原生引用
typedef size_t      size_type;          // 容器unsigned类型
typedef ptrdiff_t   different_type;     // 容器signed类型

 2.2. Vector 成员变量

iterator start;             // 表示目前使用空间的头
iterator finish;            // 表示目前使用空间的尾
iterator end_of_storage;    // 表示目前可用空间的尾

 2.3. Vector 构造函数

vector() : start(0),finish(0),end_of_storage(0) {}
vector(size_type n, const T& value)
{
    start  = allocate_and_fill(n, value); //申请一段连续内存地址,并填充n个value值
    finish = start + n;
    end_of_storage = finish;
}
vector(int n, const T& value)
{
    start  = allocate_and_fill(n, value);
    finish = start + n;
    end_of_storage = finish;
}
vector(long n, const T& value)
{
    start  = allocate_and_fill(n, value);
    finish = start + n;
    end_of_storage = finish;
}
explicit vector(size_type n)
{
    start  = allocate_and_fill(n, T()); //explicit关键字的作用就是防止类构造函数的隐式自动转换.
    finish = start + n;
    end_of_storage = finish;
}

2.4. Vector 常用函数

iterator begin()
{
    return start;
}
iterator end()
{
    return finish;
}
iterator size()
{
    return size_type(end()-begin());
}
size_type capacity()
{
    return size_type(end_of_storage - begin());
}
bool empty()
{
    return begin() == end();
}
reference operator[](size_type n)
{
    return *(begin()+n);
}
reference front()
{
    return *begin();
}
reference back()
{
    return *(end()-1);
}
reference push_back(const T& x)
{
    if (finish != end_of_storage) { // 如果内存足够
        construct(finish,x); //在finish所指之处产生x的复制品
        ++finish;
    } else {
        insert_aux(end(),x); //在end()后新增x
    }
}
void push_back()
{
    --finish;
    destory(finish); //摧毁finish
}
iterator erase(iterator position)
{
    if (position+1 != end())
        copy(position+1,finish,position); //后续元素往前移动
    --finish;
    destroy(finish);
    return position;
}
void resize(size_type new_size, const T& x)
{
    if (new_size < size())
        erase(begin()+new_size,end());
    else
        insert(end(),new_size-size(),x);
}
void resize(size_type new_size)
{
    resize(new_size,T());
}
void clear()
{
    erase(begin(),end());
}

值得一提的是,所谓动态增加大小,并不是在原空间之后接续新空间,因为无法保证原空间之后尚有可供配置的空间,而是以原大小的两倍或者更大配置一块较大空间,然后将原内容拷贝过来,最后才开始在原内容之后构造新元素,并释放原空间。

因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器将全部失效。

发布了126 篇原创文章 · 获赞 219 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/yz930618/article/details/90404236