C++ STL容器Vector的实现原理与模拟实现vector

1.vector 的数据结构

     vector采用简单的线性连续空间,两个迭代器start和end分别指向头尾,并以迭代器end_of_storage指向容量尾端。容量可能比(尾-头)还大,多余即备用空间。简单来说就是,每个动态数组都分配有一定容量,当存储的数据达到容量的上限的时候,就重新分配内存

两个迭代器start和end分别指向头尾,并以迭代器end_of_storage指向容量尾端。容量可能比(尾-头)还大,多余即备用空间。

以前一直以为在原来数组开辟的空间后面再增加,结果怎么想都没想明白。因为一般来说后面的内存已经被占用了,在后面增加是不可能的。结果是重新开辟了一个数组,把之前的值放到复制到新开辟的数组中来。

关于vector简单的说就是一个动态增长的数组,里面有一个指针指向一片连续的内存空间,当空间装不下要容纳的数据的时候会自动申请一片更大的空间(空间配置器)将原来的数据拷贝到新的空间,然后就会释放旧的空间。当删除的时候空间并不会释放只是清空了里面的数据。

 

 使用start、finish、end_of_storage三个迭代器,便可轻易地提供首尾标示、大小、容量、空容器判断、中括号运算符value计算、首元素值、尾元素值等。

                                 è¿éåå¾çæè¿°

两个关键大小: 
大小:size=_Mylast - _Myfirst; 
容量:capacity=_Myend - _Myfirst; 
分别对应于resize()、reserve()两个函数。 
size表示vector中已有元素的个数,容量表示vector最多可存储的元素的个数;为了降低二次分配时的成本,vector实际配置的大小可能比客户需求的更大一些,以备将来扩充,这就是容量的概念。即capacity>=size,当等于时,容器此时已满,若再要加入新的元素时,就要重新进行内存分配,整个vector的数据都要移动到新内存。二次分配成本较高,在实际操作时,应尽量预留一定空间,避免二次分配。 

2.下面是STL库中Vector 所对应的库函数

 3.模拟实现vector

#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma once
//vector:动态的顺序表

namespace bite{
	template<class T>
	class vector{
	public:
		typedef T* iterator;
		typedef T* reverse_iterator;
	public:
		//construct构造
		vector()
			:_start(nullptr)
			, _finish(nullptr)
			, _endofStorage(nullptr){}

		vector(size_t n, const T& value){
			_start = new T[n];
			//向空间中存放n个值为value的元素
			for (size_t i = 0; i < n; ++i)
				_start[i] = value;

			_finish = _endofStorage = _start + n;
		}
		vector(T* first, T* last){
			size_t n = last - first;
			_start = new T[n];
			while (fiwst != last){
				*_finish++ = *first++;
			}
			_endofStorage = _finish;
		}

		//注意浅拷贝
		vector(const vector<T>& v);
		vector<T>& operator=(const vector<T>& v);
		~vector(){
			if (_start){
				delete[]_start;
				_start = _finish = _endofStorage = nullptr;
			}
		}
		//iterator迭代器
		//迭代器类似指针
		//第一个有效元素的位置
		iterator begin(){
			return _start;
		}
		//最后一个有效元素的位置
		iterator end(){
			return _finish;
		}

		reverse_iterator rbegin(){
			return end();
		}
		reverse_iterator rend(){
			return begin();
		}

		//capacity
		size_t size()const{
			return _finish - _start;
		}
		size_t capacity()const{
			return _endofStorage - _start;
		}
		bool empty()const{
			return _start == _finish;
		}
		//T():创建一个无名的对象
		//T是内置类型,T()----->0
		//T是自定义类型,T()--->调用该类无参的构造函数创建对象
		void resize(size_t newSize, const & val = T()){
			size_t oldSize = size();
			if (newSize <= oldSize){
				_finish = _start + newSize;
			}
			else{
				//考虑是否需要扩容
				if (newSize > capacity())
					reserve(newSize);
				//填充元素
				for (size_t i = oldSize; i < oldSize; ++i)
					*_finish++ = val;
			}
		}
		void reserve(size_t newCapacity){
			size_t oldCapacity = capacity();
			if (newCapacity>oldCapacity){
				//申请新空间
				T* pTemp = new T[newCapacity];
				//拷贝元素
				size_t n = size();
				if (_start){
					for (size_t i = 0; i < size(); ++i)
						pTemp[i] = _start[i];
					//释放旧空间
					free(_start);
				}
				_start = pTemp;
				_finish = _start + n;
				_endofStorage = _start + oldCapacity;

			}
		}
		//access
		//访问任意位置的元素,index不能大于元素的个数
		T& operator[](size_t index){
			assert(index < size());
			return _start[index];
		}
		const T& operator[](size_t index)const{
			assert(index < size());
			return _start[index];
		}
		T& front(){
			return *_start;
		}
		const T& front()const{
			return *_start;
		}

		T& back()const{
			return *(_finish - 1);
		}
		void push_back(const T& value){
			checkcapacity();
			*_finish++ = value;
		}
		void pop_back(){
			if (empty())
				return;
			--_finsih;
		}
		iterator insert(iterator pos, const T& value){
			checkcapacity();
			//搬移元素
			for (size_t i = size(); i >= pos - _start; i--){
				_start[i] = _start[i - 1];
			}
			//插入元素
			*pos = value;
			++_finish;
			return pos;
		}
		iterator erase(iterator pos){
			if (pos == end())
				return pos;
			for (size_t i = pos - _start; i < size(); ++i){
				_start[i] = _start[i + 1];
			}
			--_finish;
			return pos;
		}
		void swap(vector<T>& v){
			swap(_start, v._start);
			swap(_finish, v._finish);
			swap(_endofStorage, v._endofStorage);
		}
		void clear(){
			_finish = _start;
		}
	protected:
		void checkcapacity(){
			if (_finish == _endofStorage)
				reserve(capacity() * 2);
		}
	protected:
		T* _start;
		T* _finish;
		T* _endofStorage;
	};
}
#include<iostream>
using namespace std;
void TestVector1(){
	bite::vector<int> v1;
	bite::vector<int> v2(10, 6);
	cout << v2.sie() << endl;
	cout << v2.capacity() << endl;
	for (auto e : v2)
		cout << e << " ";
	cout << endl;
	int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	bite::vector<int> v3(array, array + sizeof(array) / sizeof(array[0]));
	for (auto e : v3)
		cout << e << " ";
	cout << endl;
}
void Testvector2(){
bite:vector<int>v;
	v.reserve(10);
	cout << v.size() << endl;
	cout << v.capacity() << endl;
	v.reserve(5);
	cout << v.size() << endl;
	cout << v.capacity() << endl;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	cout << v.size() << endl;
	cout << v.front() << endl;
	cout << v.back() << endl;
	cout << v[1] << endl;
	for (auto e : v)
		cout << e << " ";
	cout << endl;
	v.pop_back();
	cout << v.size() << endl;
	for (auto e : v)
		cout << e << " ";
	cout << endl;

	v.pop_back();
	cout << v.back() << endl;

	v.insert(v.begin(), 0);
	cout << v.front() << endl;

	v.erase(v.begin());
	cout << v.front << endl;

	v.resize(5, 8);
	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
		cout << e << " ";
	cout << endl;

	v.resize(20);
	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
		cout << e << " ";
	cout << endl;

	v.resize(10);
	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
		cout << e << " ";
	cout << endl;

	v.clear();
	cout << v.size() << endl;
	cout << v.capacity() << endl;
}


#include<iostream>
using namespace std;

#include "Vector.h"

int main(){
	TestVector1();
	Testvector2();
	return 0;
}

4.使用STL进行操作

   4.1 向量的初始化操作

vector<int> a ;                                //声明一个int型向量a
vector<int> a(10) ;                            //声明一个初始大小为10的向量
vector<int> a(10, 1) ;                         //声明一个初始大小为10且初始值都为1的向量
vector<int> b(a) ;                             //声明并用向量a初始化向量b
vector<int> b(a.begin(), a.begin()+3) ;       //将a向量中从第0个到第2个(共3个)作为向量b的初始值

int n[] = {1, 2, 3, 4, 5} ;
vector<int> a(n, n+5) ;              //将数组n的前5个元素作为向量a的初值
vector<int> a(&n[1], &n[4]) ;        //将n[1] - n[4]范围内的元素作为向量a的初值

 4.2 元素的输入与访问‘’

/*************************************************
Copyright © ZJL 1998-2019. All rights reserved.
File name: STL_  Vector的常见用法总结
Author: ZJL
Version: V1.0
Description: Vecto本身是可以作为数组使用的,而且在一些元素不确定的场合可以很好地节省空间
Others: // 其它内容的说明
Log: 元素的初始化操作与输出操作
*************************************************/
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;

int main(int argc, char *argv[])
{
  /*  vector<int>  a(10,0);   //定义10个元素的大小为0的向量
    cin>>a[2];
    cin>>a[8];
    cin>>a[6];*/
    int n[]={1,3,4,5,6};
   // vector<int> a(n,n+5);
    vector<int> a(&n[1], &n[4]) ;//将n[1] - n[4]范围内的元素作为向量a的初值
    /**输出向量中的元素**/
    int i;
    cout<<"向量的大小:="<<a.size()<<endl;
    /**采用遍历数组的方法**/
    cout<<"---------采用遍历数组的方法---------------"<<endl;
    for(i=0;i<a.size();i++)
        cout<<a[i]<<endl;
    cout<<"---------采用迭代器---------------"<<endl;;
    vector<int>::iterator it;
    for(it=a.begin();it!=a.end();it++)
        cout<<*it<<" ";
    return 0;
}

4.3 容量函数

/*************************************************
Copyright © ZJL 1998-2019. All rights reserved.
File name: Vector ---容量函数
Author: ZJL
Version: V1.0
Description: 容器大小:vec.size();
容器容量:vec.capacity(); // 指在发生 realloc 前能允许的最大元素数,即预分配的内存空间,与 size() 不同
容器最大容量:vec.max_size();
更改容器大小:vec.resize();
容器判空:vec.empty();
Others: // 其它内容的说明
Log: 元素的初始化操作与输出操作
*************************************************/
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;

int main(int argc, char *argv[])
{
     vector<int>  vec;
     for(int i=0;i<16;i++)
     {
         vec.push_back(i);
     }
     cout<<"size():"<<vec.size()<<endl;
     cout<<"capacity"<<vec.capacity()<<endl;
     cout<<"max_size:"<<vec.max_size()<<endl;
     vec.resize(10);
     cout<<"vec.size()"<<vec.size()<<endl;
     if(vec.empty())
         cout<<"元素为空"<<endl; //输出元素为空
     return  0;

}

4.4 添加函数

/*************************************************
Copyright © ZJL 1998-2019. All rights reserved.
File name: Vector ---容量函数
Author: ZJL
Version: V1.0
Description:
末尾添加元素:vec.push_back(const T& x);
任意位置插入一个元素:vec.insert(iterator it, const T& x);
任意位置插入 n 个相同元素:vec.insert(iterator it, int n, const T& x);
插入另一个向量的 [first,last] 间的数据:vec.insert(iterator it, iterator first, iterator last);
Log: 元素的初始化操作与输出操作
*************************************************/
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;

int main(int argc, char *argv[])
{
    vector<int>  vec;
    vec.push_back(2);
    /**在人任意位置插入一个元素**/
    vector<int>::iterator it=vec.begin();
    vec.insert(it,2);
    //任意位置插入n个相同的像素
    it=vec.begin();
    vec.insert(it,3,9);  //从0 1 2 分别插入数据3个相同的数 9
    //插入另一个向量的[first,last] 间的数据
    vector<int>  vec2(2,4); //定义一个int 类型的向量vecto,设置size 为2 初始化值均为4
    cout<<"vec2.size()"<<vec2.size()<<endl;
    it=vec.begin();
    vec.insert(it,vec2.end()-2,vec2.end());
    //遍历显示数据
    for(it=vec.begin();it!=vec.end();it++)
        cout<<*it<<" ";
    cout<<endl;

     return  0;

}

4.5  删除函数

   

/*************************************************
Copyright © ZJL 1998-2019. All rights reserved.
File name: Vector ---容量函数
Author: ZJL
Version: V1.0
Description:
末尾删除元素:vec.pop_back();
任意位置删除一个元素:vec.erase(iterator it);
删除 [first,last] 之间的元素:vec.erase(iterator first, iterator last);
清空所有元素:vec.clear();
Log: 建议采用debug 打断点的方式观察数组中的元素
*************************************************/
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;

int main(int argc, char *argv[])
{
  vector<int>  vec;
  for(int i=0;i<8;i++)
      vec.push_back(i);
  //末尾删除,,末尾删除元素
  vec.pop_back();
  //在任意一个位置删除元素
  vector<int>::iterator  it;
  it=vec.begin();
  vec.erase(it);
  //删除【first,last】之间的任意一个元素
  vec.erase(vec.begin(),vec.begin()+1);
  //删除完元素之后再次观察删除玩的数组
  for(it=vec.begin();it!=vec.end();it++)
      cout<<*it<<" ";
  cout<<endl;
  //清空所有元素
  vec.clear();
  //再次遍历数组中得元素
  for(it=vec.begin();it!=vec.end();it++)
      cout<<*it<<endl;
     return  0;

}

4.6 访问函数

4.7 多个元素赋值

4.8 迭代器与算法

4.9 利用Vector 实现二维数组

/*************************************************
Copyright © ZJL 1998-2019. All rights reserved.
File name: Vector ---容量函数
Author: ZJL
Version: V1.0
Description:
实现二维数组
Log: 建议采用debug 打断点的方式观察数组中的元素
*************************************************/
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;


int main(int argc, char *argv[])
{
    const  int count=3;  //定义列
    vector<vector<int>> vec1(count);//定义一个二维数组
    for(int i=0;i<vec1.size();++i) {   //定义行
        for(int j=0;j<count;++j){
        vec1[i].push_back(333);
    }
    }
    //增加一行
    vector<int>  temp;
    vec1.push_back(temp);
    int pos=vec1.size()-1;
    //因为这里是三列
     vec1[pos].push_back(22);
     vec1[pos].push_back(22);
     vec1[pos].push_back(22);
    //增加一列
     pos=vec1.size();
     for(int i=0;i<pos;++i)
         vec1[i].push_back(555);
    //打印二维数组
    for(int i=0;i<vec1.size();++i){
        for(int j=0;j<vec1[0].size();++j){
            cout<<vec1[i][j]<<" ";}
         cout<<endl;
    }
    cout<<endl;
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值