vector常用接口实现

目录

一、需要注意的问题-关于扩容拷贝原空间的内容不能用memcpy

二、关于vector模板类的模拟实现:

三、动态二维数组理解


一、需要注意的问题-关于扩容拷贝原空间的内容不能用memcpy

假设模拟实现的vector中的reserve接口中,使用memcpy进行的拷贝,以下代码会发生什么问题?

int main()
{
 bite::vector v;
 v.push_back("1111");
 v.push_back("2222");
 v.push_back("3333");
 return 0;
}

问题分析:

1. memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中

2. 如果拷贝的是自定义类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且 自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。

 vector常用接口实现_第1张图片

 vector常用接口实现_第2张图片

 结论:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是 浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。

二、关于vector模板类的模拟实现:

#pragma once
#include
#include
namespace bit
{
	template
	class vector
	{
	public:
		//迭代器
		typedef T* iterator;
		typedef const T* const_iterator;

		iterator begin()
		{
			return _start;
		}
		
		iterator end()
		{
			return _finish;
		}

		const_iterator begin()const//const 指示*this,调用该函数(接口)的对象是const类型(不是就转换为const,保证对象变)
		{
			return _start;
		}

		const_iterator end()const
		{
			return _finish;
		}
		//构造函数(4种)
		//默认用初始化列表,老师用c11的特性直接初始化提代

		vector()
		{}

		vector(const vector& v)
		{
			_start = new T[v.capacity()];
			size_t sz = v.size();
			for (size_t i = 0; i < sz; i++)
			{
				_start[i] = v._start[i];//在类内可以用隐式成员变量
			}
			_finish = _start + v.size();
			_endofstorage =_start+ v.capacity();
		}

		vector(size_t n, const T& val = T())//T()强制类型转换:例如char*类型,转换为是strig
		{
			resize(n, val);
		}

		vector(int n, const T& val = T())//精准匹配(用size_t的话,int与size_t不匹配,还要隐式类型转换,匹配度不如两个下模板参数迭代器构造的),防止匹配近迭代器中去,
		{
			resize(n,val);
		}
		
		template 
		vector(Inputiterator begin,Inputiterator end)
		{
			for (Inputiterator i = begin; i < end; i++)
				push_back(*i);
		}


		size_t size() const
		{
			return _finish - _start;
		}

		size_t capacity() const
		{
			return _endofstorage - _start;
		}




		void swap(vector&v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);
		}

		vector& operator=(vector v)//测试&,不行
		{
			swap(v);
			return *this;
		}


		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					//搬运数据,用memcpy为浅拷贝,拷贝的是指针
					for (size_t i=0;i= _start && pos <= _finish);//pos=_finish插入尾部

			if (_finish == _endofstorage) {
				size_t len = pos - _start;//扩容后可能迭代器失效,记录相对位置

				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);

				pos = _start + len;
			}
			
			iterator end = _finish - 1;//最好对操作对象遍历
			while (end>=pos)
			{
				//end *= (--end)*;//--end发生在左边end解引用之前吗?是的
				*(end+1) = *(end);
				--end;
			}
			
			*pos = val;
			++_finish;

			return pos;
		}

		

		//增删查改

		void push_back(const T& val)
		{
			insert(_finish,val);
		}



		void pop_back()
		{
			iterator tmp = end();//end()返回的是右值
			erase(--tmp);
		}

		iterator erase(iterator pos)
		{
			assert(pos >= _start && pos < _finish);

			iterator it = pos + 1;
			while (it < _finish)
			{
				*(it - 1) = *(it);
				++it;
			}
			--_finish;

			return pos;
		}


		~vector()
		{
			if (_start)
			{
				delete[] _start;
				_start = _finish = _endofstorage = nullptr;
			}
		}
	private:
		iterator _start = nullptr;
		iterator _finish = nullptr;//C11的新特性
		iterator _endofstorage = nullptr;
	};
}

三、动态二维数组理解

// 以杨慧三角的前n行为例:假设n为5
void test2vector(size_t n)
{
 // 使用vector定义二维数组vv,vv中的每个元素都是vector
bit::vector> vv(n);
 
 // 将二维数组每一行中的vecotr中的元素全部设置为1
 for (size_t i = 0; i < n; ++i)
 vv[i].resize(i + 1, 1);
 // 给杨慧三角出第一列和对角线的所有元素赋值
 for (int i = 2; i < n; ++i)
 {
 for (int j = 1; j < i; ++j)
 {
 vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];
 }
 }
}

 bit::vector> vv(n); 构造一个vv动态二维数组,vv中总共有n个元素,每个元素都是vector类 型的,每行没有包含任何元素,如果n为5时如下所示:

vector常用接口实现_第3张图片

 vv中元素填充完成之后,如下图所示:

vector常用接口实现_第4张图片

你可能感兴趣的:(c++深入学习—入门到精通,c++,stl,后端)