cpp中的vector

c语言中的顺序表也就是cpp中的vector,但vector用指针的方式存储数据,同时vector中可以同时存储多个自定义类型例如:vector<string>或者vector<vector<int>>来书写对象,现在我将带你了解基本的底层实现。

vector的框架

namespace xiaobo
{
	template<class T>//模板(让任何类型都能调用vector)
	class vector
	{
		typedef T* iterator;//相当于迭代器的名
	 public:
       //返回size
       size_t size()
       {
            return _finish-_start;
       }
       //返回capacity
       size_t capacity()
       {  
            return _endofstorage-_start;
       }
       //迭代器
       iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
	private:
		iterator _start;//开始
		iterator _finish;//_start+size()=_finish存储数据的指针
		iterator _endofstorage;//有多少空间相当于capacity()
	};
}

构造函数vector()

vector()
			//在定义的过程中让所有的成员为空
			:_start(nullptr),//
			_finish(nullptr),
			_endofstorage(nullptr)
		{}

析构函数~vector()

        ~vector()
		{
			delete[]_start;//释放空间
            //全部置为空
			_start = _finish = _endofstorage = nullptr;
		}

拷贝函数vector()[old]

        //老方法,过程复杂但是思路简单
        vector(const vector<T>& tmp)
		{
			_start = new T[tmp.capacity()];//深拷贝需要创建新的内存
			_finish = _start;
			_endofstorage = _start + tmp.capacity();
            //_finish来拷贝数据,后面会说明为什么不使用memset拷贝
			size_t i = 0;
			while (_finish < tmp._finish)
			{
				*_finish = tmp[i];
				++_finish;
			}
		}

拷贝函数vector()[new]

       //新方法代码简介且效率更高
       vector(const vector<T>& tmp)
			:_start(nullptr),
			_finish(nullptr),
			_endofstorage(nullptr)
		{
			reserve(tmp.capacity());
            //创建于tmp空间大小相同的内存,来减少push_back的扩容时间(提高效率)

            //用迭代器将每一个数据push_back()其中
			for (auto e : tmp)
				push_back(e);
		}

新方法需要reserve()和push_back()两个函数,因此接下来将了解两个函数的底层原理

reserve()

        void reserve(size_t n)
		{
			//判断扩容后的容量是否比capacity()大,需要扩容吗
			if (n > capacity())
			{

				//这里的sz十分重要,由于后期的释放_start后依然需要使用size()
				//但是_start释放后计算_finish-_start会导致内存错误
				size_t sz = size();
				iterator tmp = new T[n]();//开辟新的内存且初始化

				//当_start==nullptr说明第一次增加数据并没有数据需要拷贝
				if (_start)
				{
					//这里不使用memset函数拷贝原因会在最后解答
					int n = 0;
					while (tmp + n < _finish)
					{
						*(tmp + n) = *(_start + n);
						++n;
					}
					//释放old内存,防止内存泄漏
					delete[] _start;
				}

				_start = tmp;//深拷贝完成
				_finish = tmp+sz;
				_endofstorage = tmp+n;
			}
		}

push_back()

        void push_back(T x)
		{
			if (_finish == _endofstorage)//发现容量不足时,进行扩容
			{
				size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;
				//如果是第一次扩容就直接等于2否则扩大2倍
				reserve(newcapacity);
			}
			//添加数据,增加size()
			*_finish = x;
			++_finish;
		}

insert()

当提起push_back时就不得不提起insert(),因为插入函数,插入位置为最后一个时就变成了push_back()函数,接下来就是实现push_back函数的哥哥insert()

        void insert(iterator pos, T& x)
		{
			//判断是否越界
			assert(pos <= _finish&&pos>=_start);

			if (_finish == _endofstorage)//扩容
			{
				size_t n = pos - _start;
				//由于扩容会导致上一空间释放,_start和pos等等指针都会生效
				//导致无法知道pos的具体位置只能先记录下数值后面再加回来即可

				size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;
				reserve(newcapacity);
				//由于扩容导致之前的pos指针失效使得用指针加数值的方式
				pos = _start + n;
			}

			//拷贝数值
			iterator end = _finish-1;
			while (pos <= end)
			{
				*(end + 1) = *end;
				--end;
			}
			//在pos位置添加数值,增加size()
			*pos = x;
			++_finish;
		}

erase()

有增加必然会有删除erase()函数

       iterator& erase(iterator pos)
		{
			//防止超出范围
			assert(pos < _finish&&pos>=_start);
			//将pos后面位置数值往前挪即可
			iterator it = pos;
			while (it != _finish)
			{
				*it = *(it + 1);
				++it;
			}
			--_finish;
			return pos;
		}

符号重载

 operator[]

//cout<<a[0]<<endl;表明a[0]是什么

   //用于vector<int> a;
   //cout<<a[0]<<endl;表明a[0]是什么
   iterator& operator[](size_t i)
   {
      return _start+i;
   }

operator=[old]

//a=b;用vector的赋值符号重载[old]

       //old方法        
       vector<T> operator=(const vector<T>& v)
		{
			if (_start != v._start)
			{
				delete[]_start;//释放就空间
				_start = new T[v.capacity()];//开辟心空间

				//拷贝数据
				for (size_t i = 0; i < v.size(); ++i)
				{
					*(_start + i) = *(v._start+i);
				}
				_finish = v._finish;
				_endofstorage = v._endofstorage;
			}
			return *this;
		}

operator=[new]

       //利用拷贝函数拷贝出一个新空间的vector<T> v
		vector<T> operator=(vector<T> v)
		{
			if (_start != v._start)
			{
				Swap(v);//再将里面全部交换即可,而且v在函数结束时会自动释放空间
			}
		}
		void Swap(const vector& v)
		{
			//用库中的swap来交换内置类型,即可
			::swap(v._start, _start);
			::swap(v._finish, _finish);
			::swap(v._endofstorage, _endofstorage);
		}

resize()

最后一个复杂的函数resize()

        void resize(size_t n, const T& val = T())
		{
			//n小于size()时需要丢弃n以后的数据
			if (n < size())
			{
				*(_start + n) = val;
				_finish =_endofstorage= _start+n;
			}
			else
			{
				if ( n > capacity())//内存不足时扩容
				{
					reserve(n);
				}

				//让未填写数据的空间写上val
				while(_start+n<=_endofstorage)
				{
					*(_start + n) = val;
					++n;
				}
				//表明已经写满
				_finish = _endofstorage;
			}
		}

注意:memset()

由于memsert()是按字节处理也就是说:

int main()
{
	int arr[10];
	memset(arr, 0, sizeof(int) * 10);

	for (auto e : arr)
	{
		cout << e << ' ' ;
	}
	cout << endl;

	memset(arr, 1, sizeof(int) * 10);
	//memset只按字节进行修改,也就是
	//00000001 00000001 00000001 00000001

	for (auto e : arr)
	{
		cout << e << ' ';
	}
	cout << endl;

	memset(arr, 2, sizeof(int) * 10);
	//为一个int的值,所以memset只适合char使用
	//同理00000002 00000002 00000002 00000002

	for (auto e : arr)
	{
		cout << e << ' ';
	}
	cout << endl;

	return 0;
}

输出结果为

 因此不能使用memset

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值