vector的使用和底层模拟实现

爱吃喵的鲤鱼

个人主页


前言

我们已经 学习了string在来实现vector会发现他们两的结构很像,而string只支持存储字符串,vector支持任意类型;


一、vector是什么?

vector和string都一样,是c++的容器,两个的差别在于vector存储的是任意类型,string是字符串。底层结构也有所不同,string数据结构和数组相似,而vector使用3个指针控制的。

二、vector的使用

2.常用的函数代码演示

1、迭代器的使用

void func(const vector<int>& vv)
{
	vector<int>::const_iterator it = vv.begin();
	for (size_t i = 0; i < vv.size(); i++)
	{
		cout << vv[i] << " ";
	}
	cout << endl;
	while (it != vv.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	for (auto i : vv)
	{
		cout << i << " ";
	}
	cout << endl;
	
}

其实大家经常使用的范围for也是迭代器的使用;

2、常用的修改器

vector<int> vv;
vv.push_back(1);
vv.push_back(2);
vv.push_back(3);
vv.push_back(4);
vector<int>::iterator pos = find(vv.begin(), vv.end(), 2);
if (pos == vv.end())
{
	vv.insert(pos, 30);
}
for (auto i : vv)//打印元素
{
	cout << i << " ";
}
cout << endl;

vv.resize(20,0);//开20个空间并且初始化
for (auto i : vv)//打印元素
{
	cout << i << " ";
}
cout << endl;
vv.push_back(20);//尾插
for (auto i : vv)//打印元素
{
	cout << i << " ";
}
cout << endl;
vv.pop_back();
vv.pop_back();
vv.pop_back();
for (int i = 0; i < 10; i++)//循环尾删10次
{
	vv.pop_back();
}
for (auto i : vv)//打印元素
{
	cout << i << " ";
}
cout << endl;
auto it = vv.begin();
//删除偶数
while (it != vv.end())
{
	if (*it % 2 == 0)
	{
		it = vv.erase(it);//删除it位置元素

	}
	else
		it++;
}
for (auto i : vv)
{
	cout << i << " ";
}
}

3、容量

已经在上面两类中体现了 

三、底层模拟实现

1、vector构架

	template<class T>//因为vector可以容下任意类型,所以我们构建了一个模板类
class vector
{
public:
	typedef T* iterator;//对迭代器的声名
	typedef const T* const_iterator;//对const迭代器的声名
	vector()//构造函数
		:_start(nullptr)
		, _finish(nullptr)
		, _end_of_storage(nullptr)
	{}
		~vector()//析构函数
		{
			delete[]_start;
			_start = _finish = _end_of_storage = nullptr;
		}
		vector(size_t n,const T& val=T())//构造函数
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}
		}
		vector(int n, const T& val = T())//构造函数
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{

			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}
		}		
vector(const vector<T>& v)//拷贝构造
		{
			//reserve(capacity());
			_start = new T[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();
		}
private:
		//左闭右开区间
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;
	};

在我们的拷贝构造中涉及了一个深浅拷贝问题;

什么是深浅拷贝 ?

浅拷贝只是对成员变量进行了拷贝 

浅拷贝就是我们只对一块内存空间的地址进行拷贝,这个时候就会有两个指针变量指向了同一块空间,当我们对第一个成员进行析构时,这空空间已经被释放了,第二个变量再来这里析构就会让程序崩溃;

深拷贝是两块不同的空间 

深拷贝是在开辟一块空间,将原有内存中的数据一个个的拷贝到新空间中;

2、vector的迭代器函数

bool empty()//判断是否为空
{
	return _start == _finish;
}
size_t capacity() const
{
	return _end_of_storage - _start;
}
size_t size() const
{
	return _finish - _start;
}
const T& operator[](size_t pos) const
{
	assert(pos < size());
	return _start[pos];
}
size_t capacity()
{
	return _end_of_storage - _start;
}
size_t size()
{
	return _finish - _start;
}
T& operator[](size_t pos)
{
	assert(pos < size());
	return _start[pos];
}
iterator begin()
{
	return _start;
}
iterator end()
{
	return _finish;
}
const iterator begin() const
{
	return _start;
}
const iterator end() const
{
	return _finish;
}

迭代器中判断大小主要用的是地址-地址,因为一段连续的空间,地址-地址就是它的大小;

这些函数在后面使用时,我们会用到const的类型,所以构造了const的函数 

3、修改器的模拟实现

		iterator insert(iterator pos, const T& val = T())//在任意位置插入
		{
			assert(pos >= _start);
			assert(pos <= _finish);
			if (_finish == _end_of_storage)
			{
				size_t len = pos - _start;
				reserve(capacity() == 0 ? 4 : capacity() * 2);
				pos = _start + len;
			}
			iterator end = _finish - 1;//没有这个会有迭代器失效,就是构成野指针
			while (end >= pos)
			{
				
				*(end + 1) = *end;
				end--;
			}
			*pos = val;
			_finish++;
			return pos;//以后还可以在次使用
		}

		void resize(size_t n,const T& val=T())//开空间初始化
		{
			if (n < size())
			{
				_finish = _start + n;
			}
			else
			{
				if (n > capacity())
				{
					reserve(n);
				}
				while (_finish != _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}

		}
		iterator erase(iterator pos)//erase不在访问这块空间
		{
			assert(pos < _finish);
			assert(pos >= _start);
			iterator start = pos + 1;
			while (start != _finish)
			{
				*(start-1) = *start;
				start++;
			}
			_finish--;
			return pos;
		}
	void reserve(size_t n)//开辟n个空间
	{
		if (n > capacity())
		{
			size_t sz = size();
			T* tmp = new T[n];
			if (_start)
			{
				memcpy(tmp, _start, sizeof(T) * size());
			/*	for (size_t i = 0; i < size(); i++)
				{
					_start[i] = tmp[i];
				}*/
				delete[] _start;
			}
			_start = tmp;
			_finish = tmp + sz;
			_end_of_storage = tmp + n;
		}
	}
	void push_back(const T& x)//尾插
	{
		if (_finish == _end_of_storage)
		{
			reserve(capacity() == 0 ? 4 : capacity() * 2);
		}
		*_finish = x;
		_finish++;
	}
	void pop_back()//尾删
	{
		assert(!empty());
		_finish--;
	}

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃喵的鲤鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值