C++—>STL中vector使用篇+简单接口的模拟实现

在这里插入图片描述

🚩前言

前面描述了字符串string的相关知识,接下来描述第二个常用容器——vector,即顺序表。👇👇

1、vector容器的概述

  • 简单来说,vector相当于C++中的数组,数组中可以用的操作,在vector中都有相应的接口,并且具有数组没有的功能,基于数组的数据结构实现自动管理内存的,方便灵活的序列容器。

2、vector构造函数的使用

首先了解vector可以支持的构造函数有哪些?下面是所具有的构造函数:
在这里插入图片描述

//构造函数的使用
void Test_vector_1()
{
	//构造一个空的容器
	vector<int> v1;
	//构造n个值为val的容器
	vector<int> v2(8,6);
	//使用迭代器构造一个容器,可以改变范围大小
	vector<int> v3(++v2.begin(), --v2.end());
}

调试结果
在这里插入图片描述

3、vector遍历方式

在vector中和string遍历方式一样的,都包括下标访问、迭代器以及范围for访问,接下来使用一下这些访问方式:

//遍历方式的使用
void Test_vector_2()
{
	//创建一个大小为10,值为6的容器
	vector<int> v1(10,6);
	
	
	//下标访问
	for (int i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	cout << endl;

	//迭代器
	vector<int>::iterator it = v1.begin();
	while (it != v1.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	
	//范围for遍历
	for (auto n : v1)
	{
		cout << n << " ";
	}
	cout << endl;
}

在这里插入图片描述

4、vector中Capacity相关接口

在这里插入图片描述

通过reserve接口来了解:
在这里插入图片描述


//Capacity相关接口
void Test_vector_3()
{
	vector<int> v1(10,1);
	//先看原始空间大小
	cout <<"_size:"<< v1.size() << endl;
	cout << "_capacity:"<<v1.capacity() << endl;
	//申请更大空间
	v1.reserve(30);
	cout << "预留大于空间的,空间变大:" << endl;
	cout <<"_size:"<< v1.size() << endl;
	cout << "_capacity:"<<v1.capacity() << endl;
	cout << "预留比空间小的,空间不会缩容的:" << endl;
	v1.reserve(20);
	cout << "_size:" << v1.size() << endl;
	cout << "_capacity:" << v1.capacity() << endl;
}

在这里插入图片描述

resize()接口的作用

主要有两种:①resize的个数小于原本数据个数的时候,就相当于删除后面的数据内容,在vs上空间不会缩容(缩容和不缩容得看编译器平台);②若大于原本数据个数的时候,就是插入,当空间不够的时候就会扩容;

//resize()
void Test_vector_3()
{ 
	vector<int> v1(10, 1);
	//先看原始空间大小
	cout << "_size:" << v1.size() << endl;
	cout << "_capacity:" << v1.capacity() << endl;
	for (auto n : v1)
	{
		cout << n << " ";
	}
	cout << endl << endl;
	cout << "大于原有数据个数的时候,超过原有空间大小:" << endl;
	v1.resize(15,2);
	cout << "_size:" << v1.size() << endl;
	cout << "_capacity:" << v1.capacity() << endl;
	for (auto n : v1)
	{
		cout << n << " ";
	}
	cout << endl << endl;
	cout << "小于原有数据个数的时候,不会缩容:" << endl;
	v1.resize(5);
	cout << "_size:" << v1.size() << endl;
	cout << "_capacity:" << v1.capacity() << endl;
	for (auto n : v1)
	{
		cout << n << " ";
	}
	cout << endl << endl;
}

在这里插入图片描述

5、vector插入和删除的使用

插入接口主要是:push_back()和insert(),删除就是:erase();

//插入和删除
void Test_vector_4()
{
	vector<int> v1;
	cout << "size:" << v1.size() << endl;
	cout << "capacity:" << v1.capacity() << endl;
	cout << endl;
	//尾插
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);
	v1.push_back(6);
	v1.push_back(7);
	v1.push_back(8);
	v1.push_back(9);
	v1.push_back(10);
	v1.push_back(11);

	cout << "尾插:" << endl;
	for (auto n : v1)
	{
		cout << n << " ";
	}
	cout << endl;
	cout << "size:" << v1.size() << endl;
	cout << "capacity:" << v1.capacity() << endl;
	cout << endl;

	//固定插入
	cout << "首部插入:" << endl;
	v1.insert(v1.begin(),10);
	for (auto n : v1)
	{
		cout << n << " ";
	}
	cout << endl << endl;

	cout << "中间位置插入:" << endl;
	v1.insert(v1.begin()+4, 666);
	for (auto n : v1)
	{
		cout << n << " ";
	}
	cout << endl << endl;

	cout << "erase支持某一位置删除和区间删除:" << endl;
	cout << "删除第一个元素:"<<endl;
	v1.erase(v1.begin());
	for (auto n : v1)
	{
		cout << n << " ";
	}
	cout << endl << endl;
	cout << "删除最后一个元素:" << endl;
	v1.erase(v1.end()-1);
	v1.erase(v1.begin());
	for (auto n : v1)
	{
		cout << n << " ";
	}
	cout << endl << endl;
	cout << "区间删除:" << endl;
	v1.erase(v1.begin()+3,v1.begin()+5);
	for (auto n : v1)
	{
		cout << n << " ";
	}
	cout << endl << endl;
	cout << "清空接口,不改变空间:clear()" << endl;
	v1.clear();
	cout <<"size:"<< v1.size() << endl;
	cout << "capacity:"<<v1.capacity() << endl;
	cout << endl;
}

在这里插入图片描述

常用常用接口就描述到此,不常见的可以通过下面链接了解:

vector容器官方文档介绍

✨模拟实现vector简单接口

此次的模拟实现包括:迭代器遍、增删接口、空间大小改变等。通过类模版+命名空间域,以便和库里的vector区别。
再代码编写的时候容易出现迭代器失效的问题,特别是在插入和删除的时候,在代码注释中有解释;

#pragma once
#include<assert.h>


namespace zc
{
	template<class T>
	class my_vector
	{
	public:
		typedef T* iterator;
		typedef T* const_iterator;
	
		//无参构造函数
		my_vector() {};
		//n个值构造函数
		my_vector(int n, const T& value = T());
		//迭代器区间构造函数
		template<class input_iterator>
		my_vector(input_iterator first,input_iterator last);
		//拷贝构造函数
		my_vector(const my_vector<T>& v);
		//赋值拷贝构造函数
		my_vector<T>& operator=(my_vector<T> v);
		//析构函数
		~my_vector()
		{
			if (_start)
			{
				delete[] _start;
				_start = _finish = _end_of_storage;
			}
		}

		void reserve(size_t n);

		//有效数据个数
		size_t size()const
		{
			return _finish - _start;
		}
		//有效空间
		size_t capacity()const
		{
			return _end_of_storage - _start;
		}
		//改变容器大小
		void resize(size_t n,const T& value = T());


		//迭代器访问接口
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
		//const迭代器
		const_iterator begin()const
		{
			return _start;
		}
		const_iterator end()const
		{
			return _finish;
		}



		//访问数据函数接口
		T& operator[](size_t i)
		{
			assert(i < size());
			return _start[i];
		}
		const T& operator[](size_t i)const
		{
			assert(i < size());
			return _start[i];
		}


		bool empty()
		{
			return _finish == _start;
		}

		void swap(my_vector<T>& v)
		{
			//调用库里面的
			std::swap(_start,v._start);
			std::swap(_finish, v._finish);
			std::swap(_end_of_storage, v._end_of_storage);
		}

		//增删查函数接口
		void push_back(const T& x);
		void pop_back()
		{
			assert(!empty());
			--_finish;
		}
		iterator insert(iterator pos, const T& x);
		iterator erase(iterator pos);


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


	
	template<class T>
	void print_vector(const my_vector<T>& v)
	{
		typename my_vector<T>::const_iterator it = v.begin();
		while (it != v.end())
		{
			std::cout << *it << " ";
			++it;
		}
		std::cout << std::endl;
	}


	template<class T>
	inline my_vector<T>::my_vector(int n, const T& value)
	{
		reserve(n);
		for (int i = 0; i < n; i++)
		{
			push_back(value);
		}
	}

	template<class T>
	inline my_vector<T>::my_vector(const my_vector<T>& v)
	{
		//先开辟与拷贝对象中数据个数的空间
		reserve(size());
		//直接插入值
		for (auto vv : v)
		{
			push_back(vv);
		}
	}

	template<class T>
	inline my_vector<T>& my_vector<T>::operator=(my_vector<T> v)
	{
		swap(v);
		return *this;
	}

	template<class T>
	inline void my_vector<T>::reserve(size_t n)
	{
		if (n > capacity())
		{
			//注意size()的改变,需要先计算出old_size保存起来,再赋值给新空间中
			size_t old_size = size();
			//1、开辟新空间
			T* tmp = new T[n];
			//2、拷贝新空间,此处memcpy()对于要深拷贝的数据,就无法完成,因此要用赋值
			for (int i = 0; i < size(); i++)
			{
				//把原来空间中的数据拷贝过来
				tmp[i] = _start[i];
			}
			//3、释放就空间
			delete[] _start;
			//4、修改末尾大小和空间大小
			_start = tmp;
			_finish = tmp + old_size;//若此处还用size(),那么会崩掉,因为此时_start已经是新空间的了,size()中计算是_finish-_start;
			_end_of_storage = _start + n;
		}
	}

	template<class T>
	inline void my_vector<T>::resize(size_t n,const T& value)
	{
		//当n<_finish时或小于size()有效个数,相当于删除数据
		if (n < size())
		{
			_finish = _start + n;
		}
		else
		{
			//此处两种情况,1:在_finish和_end_of_storage之间,2:大于整个空间大小,则需要扩容
			//因此不管哪种直接调用reserve(),里面有检查机制,在两者之间的时候是不会扩容的
			reserve(n);
			//然后直接在末尾插入数据
			while (_finish < _start + n)
			{
				*_finish = value;
				++_finish;
			}
		}
	}

	template<class T>
	inline void my_vector<T>::push_back(const T& x)
	{
		//扩容
		if (_finish == _end_of_storage)
		{
			reserve(capacity() == 0 ? 4 : 2 * capacity());
		}
		*_finish = x;
		++_finish;
	}

	//在类外不能去没有实例化的类模版里面取东西,编译器不能区分此处的iterator是类型还是静态成员变量,
	// 需要用my_vector范围限定以及typename修饰,也可以整体写为auto,自动推导
	template<class T>
	inline typename my_vector<T>::iterator my_vector<T>::insert(typename my_vector<T>::iterator pos, const T& x)
	{
		//检查插入位置是否合理
		assert(pos >= _start && pos <= _finish);
		//扩容之前pos需哟可临时存起来,记录好相对位置,因为扩容后会导致pos失去原来的意义
		size_t len = pos - _start;
		//扩容机制
		if (_finish == _end_of_storage)
		{
			reserve(capacity()==0?4:2*capacity());
		}
		//移动位置
		pos = _start + len;		
		iterator end = _finish - 1;
		while (end >= pos)
		{
			*(end + 1) = *end;
			--end;
		}
		*pos = x;
		++_finish;

		return pos;
	}

	template<class T>
	inline  typename my_vector<T>::iterator my_vector<T>::erase(typename my_vector<T>::iterator pos)
	{
		//检查删除位置合法性
		assert(pos>=_start&&pos<_finish);
		//移动数据
		iterator begin = pos + 1;
		while (begin <= end())
		{
			*(begin - 1) = *begin;
			++begin;
		}
		--_finish;

		return pos;
	}

	template<class T>
	template<class input_iterator>
	inline my_vector<T>::my_vector(input_iterator first, input_iterator last)
	{
		while (first != last)
		{
			push_back(*first);
			++first;
		}
	}
}

测试代码

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include"my_vector.h"

void test_1()
{
	zc::my_vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);

	std::cout << "v1容器下标访问:";
	for (int i = 0; i < v1.size(); i++)
	{
		std::cout << v1[i] << " " ;
	}
	std::cout << std::endl;

	std::cout << "v1容器迭代器访问:";
	zc::my_vector<int>::iterator it = v1.begin();
	while (it != v1.end())
	{
		std::cout << *it << " ";
		++it;
	}
	std::cout<<std::endl;

	std::cout << "v1容器范围for访问:";
	for (int& x : v1)
	{
		std::cout << x << " ";
	}
	std::cout << std::endl;

	/*std::cout << "v1容器删除数据:";
	v1.pop_back();
	v1.pop_back();
	print_vector(v1);*/

	zc::my_vector<int> v2(v1.begin()+1,v1.begin()+3);
	std::cout << "v2容器迭代器区间构造:";
	print_vector(v2);

	zc::my_vector<int> v3(10,6);
	std::cout << "v3容器n个值构造:";
	print_vector(v3);

	zc::my_vector<int> v4=v3;
	std::cout << "v4容器拷贝构造:";
	print_vector(v4);

	zc::my_vector<int> v5;
	v5 = v2;
	std::cout << "v5容器赋值拷贝:";
	print_vector(v5);

	std::cout << "v1插入数据:";
	v1.insert(v1.begin()+5, 66);
	v1.insert(v1.begin() + 2, 99);
	print_vector(v1);

	std::cout << "v3删除数据:";
	v3.erase(v3.begin() + 4);
	v3.erase(v3.begin() + 5);
	v3.erase(v3.begin() + 6);
	print_vector(v3);

	std::cout << std::endl;
	std::cout << "改变v1容器大小:" << std::endl;
	std::cout << "v1原始空间大小:" << v1.capacity() << std::endl;
	std::cout << "v1原始有效个数:" << v1.size() << std::endl;
	print_vector(v1);
	v1.resize(11,5);
	std::cout << "v1改变后空间大小:" << v1.capacity() << std::endl;
	std::cout << "v1改变后有效个数:" << v1.size() << std::endl;
	print_vector(v1);

}

void test_2()
{
	zc::my_vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	std::cout << "v原始空间大小:" << v.capacity() << std::endl;
	std::cout << "v原始有效个数:" << v.size() << std::endl;
	print_vector(v);

	v.resize(7,1);
	std::cout << "v现在空间大小:" << v.capacity() << std::endl;
	std::cout << "v现在有效个数:" << v.size() << std::endl;
	print_vector(v);

}

void test_3()
{
	std::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	std::cout << v.capacity() << std::endl;
	std::cout << v.size() << std::endl;
	v.resize(7,1);
	std::cout << v.capacity() << std::endl;
	std::cout << v.size() << std::endl;
}

int main()
{
	test_1();
	//test_2();
	//test_3();
	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值