C++STL 体系结构与内核分析(侯捷)——课程笔记(六)

本部分内容包括容器vector,array和forward_list的探究。

一、vector

1. 概述

其源码如下,G2.9版本

template <class T, class Alloc = alloc>
class vector{
public:
    typedef T              value_type;
    typedef value_type*    iterator;
    typedef value_type&    reference;
    typedef size_t         size_type;
protected:
    iterator start;
    iterator finish;
    iterator end_of_storage;
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里面包含三个迭代器,vector的迭代器的类型是T*(G4.9实现得要复杂一点,但本质上还是T*)。三个迭代器分别指示元素开始位置,元素末尾位置以及容量末尾位置,所以对一个vector求sizeof的结果是12。

2. vector的扩容原理

当需要扩容时,vector会重新申请原容量两倍大小的一块内存,并把原来的元素移动到新的地址,下面以push_back()为例。

void push_back(const T& x){
    if(finish != end_of_storage){
        construct(finish, x);
        ++finish;
    }
    else
        insert_aux(end(), x);
}

template<class T, class Alloc>
void vector<T, Alloc>::insert_aux(iterator position, const T& x){
    if(finish != end_of_storage){
        //在备用空间起始处构建一个元素,并以vector最后一个元素作为其初值
        construct(finish, *(finish - 1));
        ++finish;
        T x_copy = x;
        copy_backward(position, finish - 2, finish - 1);
        *position = x_copy;
    }
    else{
        const size_type old_size = size();
        const size_type len = old_size != 0 ? 2 * old_size : 1;
        
        iterator new_start = data_allocator::allocate(len);
        iterator new_finish = new_start;
        try{
            //将原vector的内容拷贝到新vector
            new_finish = uninitialized_copy(start,
                             position, new_start);
            construct(new_finish, x);
            ++new_finish;
            //拷贝安插点后的原内容,因为这个函数也可能被insert()调用
            new_finish = uninitialized_copy(position,
                                 finish, new_finish);
        }
        catch(.....){
            //"commit or rollback" semantics
            destroy(new_start, new_finish);
            data_allocator::deallocate(new_start, len);
            throw;
        }
        //解构并释放原vector
        destroy(begin(), end());
        deallocate();
        //调整迭代器,指向新vector
        start = new_start;
        finish = new_finish;
        end_of_storage = new_start + len;
    }
}

3. vector的迭代器

G2.9版本的vector的迭代器就是一个指针,类型为T*,所以使用iterator_traits时调用的是指针的偏特化版本。

G4.9版本的迭代器相当复杂,大概就是iterator是一种__normal_iterator<>,而__nomal_iterator<>是一个定义了五种类型的class。实际上G4.9的迭代器从根本上的类型还是T*,只不过包装得十分复杂,源码就不抄了,PPT如下:

二、array

array就是把C风格数组包装成容器的形式

1. TR1版本源码

template<typename _Tp, std::size_t _Nm>
struct array
{
    typedef _Tp            value_type;
    typedef _Tp*           pointer;
    typedef value_type*    iterator;

    value_type _M_instance[_Nm ? _Nm : 1];

    iterator begin()
    { return iterator(&_M_instance[0]); }

    iterator end()
    { return iterator(&_M_instance[_Nm]); }

    ......
};

注意其没有构造函数和析构函数

2. G4.9版本源码

注意右上角typedef对于数组的用法,这是理解array的成员_M_elems的类型的关键。

三、forward_list

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值