vector的实现原理

vector 是一段连续的线性内存空间。

Vector类维护3 个迭代器(三个类型指针)来表示:

start,finish,end_of_storage
其中,start 指向的是 vector 容器对象的起始字节位置;last 指向当前最后一个元素的末尾字节;end_of_storage指向整个 vector 容器所占用内存空间的末尾字节。

start 和 finish 可以用来表示 vector 容器中目前已被使用的内存空间;
finish和 end_of_storage 可以用来表示 vector 容器目前空闲的内存空间;
start 和 end_of_storage可以用表示 vector 容器的容量。

对于空的 vector 容器,由于没有任何元素的空间分配,因此 start,finsh 和 end_of_storage 均为 null。

当我们使用vector::iterator it;时,it就是TYPE* 类型指针,上述三个迭代器也是如此。

通过灵活运用这 3 个迭代器,vector 容器可以轻松的实现诸如首尾标识、大小、容器、空容器判断等几乎所有的功能,比如:

template <class _Ty, class _Alloc = allocator<_Ty>>
class vector{
public:
    iterator begin() {return start;}
    iterator end() {return finish;}
    size_type size() const {return size_type(end() - begin());}
    size_type capacity() const {return size_type(end_of_storage - begin());}
    bool empty() const {return begin() == end();}
    reference operator[] (size_type n) {return *(begin() + n);}
    reference front() { return *begin();}
    reference back() {return *(end()-1);}
    ...
};

我们可以看出,通过上述的三个指针,几乎所有的操作都可以进行了。值得一提的是vector重载了[ ],可以方便存取值。

需要注意的是,当我们访问尾元素时,迭代器可不是*.end(),而是*.end()-1。

vector扩容机制

另外需要指明的是,当 vector 的大小和容量相等(size==capacity)也就是满载时(end_of_storage不够时),如果再向其添加元素,那么 vector 就需要扩容。vector 容器扩容的过程需要经历以下 3 步:
完全弃用现有的内存空间,重新申请更大的内存空间;(重新配置)
将旧内存空间中的数据,按原有顺序移动到新的内存空间中;(元素搬移)
最后将旧的内存空间释放。( 这也就解释了,为什么 vector 容器在进行扩容后,与其相关的指针、引用以及迭代器可能会失效的原因。(释放原内存))

由此可见,vector 扩容是非常耗时的。为了降低再次分配内存空间时的成本,每次扩容时 vector 都会申请比用户需求量更多的内存空间(这也就是 vector 容量的由来,即 capacity>=size),以便后期使用。

vector 容器扩容时,不同的编译器申请更多内存空间的量是不同的。以 VS 为例,它会扩容现有容器容量的 50%。(一般都是扩容两倍)

源码:

template<class T1, class T2>
inline void construct(T1* p, const T2& value)
{
    new(p) T1(value);    //placement new, 调用T1::T1(value);
}
template <class T, class Alloc = alloc>
void vector<T, Alloc>::insert_aux(iterator position, const T& x)
{
    //还有备用空间
    if (finish != end_of_storage)
    {
        //在备用空间起始处构造一个元素,并以vector最后一个值为其初值
        construct(finish, *(finish - 1));
        //调整水位
        ++finish;
        //拷贝一个元素
        T copy_x = x;
        //把vector插入位置position之后的元素往后移一位
        copy_backward(position, finish - 2, finish - 1);
        //给position指向的地方赋值,赋值内容为前面拷贝的元素
        *position = copy_x;
    }
    //已无备用空间
    else
    {
        const size_type old_size = size();
        //如果原来的vector为空,则申请一个元素的空间,否则申请可以容纳原来2倍元素的空间
        const size_type len = old_size == 0 ? 1 : 2 * old_size;
        //全局函数,申请空间
        iterator new_start = data_allocator::allocate(len);
        iterator new_finish = new_start;
 
        try
        {
            //将原来vector的position之前的内容拷贝到新的vector前面
            new_finish = uninitialized_copy(start, position, new_start);
            //调用构造函数为新插入的元素赋值
            construct(new_finish, x);
            //调整水位
            ++new_finish;
            //将原来vector的postion之后的内容拷贝到新的vector后面
            new_finish = uninitialized_copy(position, finish, new_finish);
        }
        catch (...)
        {
            //析构
            destroy(new_start, new_finish);
            //释放刚刚申请的内存
            data_allocator::deallocate(new_start, len);
            throw;
        }
 
        //析构原vecotr
        destroy(begin(), end());
        //释放原vector的空间
        deallocate();
        
        //调整迭代器指向新的vector
        start = new_start;
        finish = new_finish;
        end_of_storage = new_start +len;
    }
}

void push_back(const T& x)
{
    if(finish!=end_of_storage)//还有备用空间
    {
        construct(finish,x);
        ++finish;          
    }
    else//以无备用空间
    {
        insert_aux(finish, x);
    }
}
vectorC++标准库中的一个容器,用于存储动态大小的元素序列。它是通过动态分配内存来实现的,其内部使用了一个动态数组来存储元素。 vector实现原理主要包括以下几个方面: 1. 动态内存分配:vector使用动态分配的方式来管理内存,当元素数量超过当前分配的内存空间时,会自动进行内存的重新分配和拷贝。一般情况下,vector会分配比实际元素数量更多的内存空间,以便在需要添加新元素时不必频繁进行内存重新分配。 2. 元素访问:vector可以通过下标或迭代器来访问元素,下标操作符[]和at()函数都可以用于访问指定位置的元素。vector的内部实现是一个连续的动态数组,因此可以通过偏移量来计算指定位置的元素地址,从而实现高效的元素访问。 3. 元素插入和删除:在向vector中插入或删除元素时,需要考虑到动态内存的重新分配和元素的移动。当插入或删除元素时,如果当前容量不足,vector会重新分配更大的内存空间,并将原有元素复制到新的内存区域中。插入和删除元素可能导致其他元素的位置发生变化,需要进行元素的移动和调整。 4. 内存管理:vector使用动态分配的内存,因此需要负责内存的申请和释放。当vector销毁或清空时,会释放已分配的内存空间,防止内存泄漏。 总的来说,vector通过动态分配内存和数组操作实现了动态大小的元素序列,并提供了高效的元素访问、插入和删除操作。它是一种常用的容器,在C++编程中广泛应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值