C++ vector详解

vector的基本使用

vector是C++中非常常见的容器,可以存储任意类型的数据,而vector也可以成为动态数组,他是支持扩容和缩容的,下面来介绍一些vector的接口:
在这里插入图片描述
1,创建
头文件:#include
vector<数据类型> 自定义名称
在这里插入图片描述
也可以使用另一个vector来初始化
在这里插入图片描述
在这里插入图片描述
也可以在初始化时,指定大小和参数
在这里插入图片描述
如果只指定大小,里面的值默认是0
在这里插入图片描述
也可以用迭代器和指针来初始化

在这里插入图片描述
在这里插入图片描述

2,插入
push_back:尾插数据

在这里插入图片描述
emplace_back:尾插数据
在这里插入图片描述

insert:指定位置前一个位置插入数据(参数为迭代器和要插入的值)
在这里插入图片描述

3,删除
pop_back:尾删
在这里插入图片描述

erase:删除指定数据(参数是迭代器)
删除指定单个数据
在这里插入图片描述

删除指定区间数据
在这里插入图片描述

clear:清空所有数据
在这里插入图片描述

4,扩容和获取容器大小
size:获取容器有效运输个数
在这里插入图片描述

capactiy:获取容器总大小
在这里插入图片描述

reserve:将容器总空间扩容
在这里插入图片描述

resize:将情况有效数据的个数进行扩容
在这里插入图片描述
也可以在扩容的同时,初始化
在这里插入图片描述

5,缩容

有效数据空间缩容(resize)
在这里插入图片描述
有效数据空间缩容,并不会影响总空间大小

6,其他接口
size:返回有效数据个数
capacity:返回总空间大小
max_size:返回容器的大小
bagin:返回第一个元素的迭代器
end:返回最后一个元素的迭代器的下一个位置
rbegin:返回最后一个元素的的迭代器
rend:返回第一个元素的迭代器的上一个位置
cbegin:返回第一个元素
cend:返回最后一个元素
empty:判断容器是否为空
at:查找某个元素是否在容器内
back:返回最后一个元素

vector的模拟实现

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;

namespace ys
{
	template<class T>
	class vector
	{
		

	public:
		typedef T* iterator;
		typedef const T* const_iterator;

		vector()
			:_start(nullptr)
			,_finish(nullptr)
			,_end_of_storage(nullptr)
		{
			
		}
		vector(size_t n,const T& i = T())
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(n);
			for (int x = 0; x < n; x++)
			{
				push_back(i);
			}
		}

		template<class InputIterator>
		vector(InputIterator begin, InputIterator end)
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			while (begin != end)
			{
				push_back(*begin);
				begin++;
			}
		}

		vector(vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(v.capacity());
			int size = v.size();
			for (int i = 0; i < size; i++)
			{
				push_back(v[i]);
			}
		}

		void swap(vector<T>& v)
		{
			std::swap(_start,v._start);
			std::swap(_finish,v._finish);
			std::swap(_end_of_storage,v._end_of_storage);
		}

		vector<int>& operator = (vector<T> v)
		{
			swap(v);
		}

		vector(const vector<T>& v)
		{
			//_start = new T[v.capacity()];
			memcpy(_start, v._start, sizeof(T)*v.size());
			//for (size_t i = 0; i < v.size(); ++i)
			//{
			//	_start[i] = v._start[i];
			//		
			//}

			//_finish = _start + v.size();
			//_end_of_storage = _start + v.capacity();

			//现代写法
			//创建一个临时对象,然后使用swap交换
			vector<T> x(v.begin,v.end);
			swap(x);
		}

		//返回有效数据个数
		size_t size()
		{
			return _finish - _start;
		}

		//扩容总空间
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				//记录finish位置
				int i = _finish - _start;
				
				//拷贝数据
				T* tmp = new T[n];
				if (_start)
				{
					memcpy(tmp,_start,sizeof(T) * size());
					//释放旧空间
					delete[] _start;
				}
				
				//更新地址
				_start = tmp;
				_finish = _start + i;
				_end_of_storage = _start + n;
			}
			
		}

		//扩容有效空间并初始化
							 //带参的函数重载
		void resize(size_t n,T pos = T())
		{
			//判断扩容
			if (n > capacity())
			{
				//扩容
				reserve(n);
				while (_finish != _start + n)
				{
					*_finish = pos;
					++_finish;
				}
			}
			else if (n < size())
			{
				//缩容,有效数据缩容,而不是缩容整个空间大小
				_finish = _start + n;
			}

			//if (n < size())
			//{
			//	// 删除数据
			//	_finish = _start + n;
			//}
			//else
			//{
			//	if (n > capacity())
			//		reserve(n);

			//	while (_finish != _start + n)
			//	{
			//		*_finish = pos;
			//		++_finish;
			//	}
			//}

			
		}

		//尾插
		void push_back(T x)
		{
			//判断容量
			if (_finish == _end_of_storage)
			{
				//扩容
				reserve(_finish - _start == 0 ? 4 : capacity() * 2);
			}

			*_finish = x;
			_finish++;
		}

		//尾删
		void pop_back()
		{
			assert(!empty());
			_finish--;
		}

		//指定位置插入
		iterator insert(iterator pos, const T& val)
		{
			assert(pos >= _start);
			assert(pos <= _finish);

			if (_finish == _end_of_storage)
			{
				//扩容前记录迭代器的位置,防止迭代器失效
				size_t i = pos - _start;

				//扩容
				reserve(capacity() == 0 ? 4 : capacity() * 2);

				//更新pos的位置
				pos = _start + i;
			}
			
			//将数据向后挪动
			T* end = _finish + 1;
			while (end >= pos)
			{
				*end = *(end - 1);
				end--;
			}

			//插入数据
			*pos = val;
			//有效数据个数++
			_finish++;
			//返回当前位置的迭代器
			return pos;
		}

		//指定位置删除
		void erase(iterator pos)
		{
			assert(pos >= _start);
			assert(pos < _finish);

			T* end = pos;
			while (end < _finish)
			{
				*end = *(end + 1);
				end++;
			}

			--_finish;

			/*assert(pos >= _start);
			assert(pos < _finish);

			iterator start = pos + 1;
			while (start != _finish)
			{
				*(start - 1) = *start;
				++start;
			}

			--_finish;*/
		}

		//判空
		bool empty()
		{
			return _finish == _start;
		}

		//返回总空间大小
		size_t capacity()
		{
			return _end_of_storage - _start;
		}

		//迭代器
		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}

		iterator const_begin() const
		{
			return _start;
		}

		iterator const_end() const
		{
			return _finish;
		}

		T& operator[](size_t i)
		{
			assert(!empty());
			return _start[i];
		}

	private:
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;
	};
}

vector迭代器问题

1,迭代器失效问题:
在这里插入图片描述
此时i是否还能解引用操作呢?
不能,如果强行去解引用,会报错
但是可以erase函数会返回删除后的下一个元素的迭代器
在这里插入图片描述

2,反向迭代器
在使用正向迭代器,begin,end的时候
如果想要往后走,可以使用++操作,往前走可以使用–操作
在++和–操作的时候,逻辑结构是线性的

使用反向迭代器,rbeign返回的是最后一个元素的下一个位置,rend返回的是第一个元素的位置,如果要通过rbegin或者end遍历容器,比如说用rbegin从后向前遍历,应该让rbegin每次 – ,可设计师却不这么想,如果想要用rbegin向后走,要用++,也就是说rbegin的++和–操作是相反的:
在这里插入图片描述
同理,如果用rend去遍历,要用–:
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值