STL分析(五 vector,array和forward_list)

vector

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:
	typedef simple_alloc<value_type, Alloc> data_allocator;//simple_alloc是
    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); }
};
  1. 注意到vector的迭代器类型为value_type*,即T*。相比于list中的迭代器声明一个新的类要简单,这是因为vector为分配的顺序结构,不需要定义节点前后指针。
  2. vector中包含三个迭代器,分别指向元素开始位置,元素末尾位置(前闭后开),容器末尾位置。
  3. vetcor的大小为其成员即三个指针的大小sizeof(vector< T>)=12

vector扩容原理

当vector进行push_back()或insert()操作时,若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-1位置的元素挪到finsh
        ++finish;//finish后退
        T x_copy = x;
        copy_backward(position, finish - 2, finish - 1);//将pos到finish-2处元素全部往后退
        *position = x_copy;//将待插入的元素插入position
    }
    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;
    }
}

其中的construct和destroy源自allocator,可被全局调用,源码如下

// 自定义空间配置器
template<typename T>
struct myallocator
{
	// 开辟内存空间
	T* allocate(size_t size) 
	{
		return (T*)::operator new(sizeof(T)*size);// 相当于malloc分配内存
	}
	// 释放内存空间
	void deallocate(void *ptr, size_t size)
	{
		::operator delete(ptr, sizeof(T)*size);// 相当于free释放内存
	}
	// 负责对象构造
	void construct(T *ptr, const T &val)
	{
		new ((void*)ptr) T(val);// 用定位new在指定内存上构造对象
	}
	// 负责对象析构
	void destroy(T *ptr)
	{
		ptr->~T();// 显示调用对象的析构函数
	}
};

四个函数作用如下:
在这里插入图片描述

vector的iterator

既然vector是连续空间,其iterator可以不用设计成为一个class,将指针作为其迭代器 。
在G2.9版本中,当iterator对象放入iterator_traits中,被识别为T*的native pointer偏特化版本。
在这里插入图片描述
在G4.9版本中,iterator是一种_normal_iterator<>,他是一种定义了五种iterator基本类型的class,而_normal_iterator<>中包含继承自_Vector_base<>中的指针成员,这个指针成员由继承自_alloc_traits<>,根本类型上还是T *。
在这里插入图片描述

在4.9版中iterator对象放入iterator-traits被识别为class版本

array

G2.9版本

把C风格数组包装为容器形式

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]); }
 
    ......
};
  • 定义一个类型为value_type的_M_instance数组,以Nm为总大小,当Nm为0时,自动生成大小为1的数组
  • begin()指向数组第0个,end()指向数组第最后一个元素(前开后闭)
  • array没有ctro和dtor
  • array也是连续空间,其iterater也是native pointer,交给iterator_traits时调用T*的版本

使用array时要指定大小

array<int, 10> myArray;
auto ite = myArray.begin();

G4.9版本

在这里插入图片描述
在typedef用法中,将_Type指代为_Tp[_Nm]的数组,并在函数传入参数时直接使用_Type类型数组_M_elems。

forward_list

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值