vector类模拟实现及代码易错点解析(建议从test_vector1看)

#pragma once
#include 
#include
#include 
#include 
using namespace std;
namespace zm
{
	template
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;//const在*左边,代表内容不能改变

		vector()
			/*:_start(nullptr),
			_finsh(nullptr),
			_end_of_storage(nullptr)*/
		{}
		//vector v1(10, 6);  这里10被系统认为是int 与size_t发生转换 
		vector(size_t n, const T& val = T())//T调用默认构造生成匿名对象 默认构造定义:无参,全缺省的,我们没写系统默认生成的,并且默认构造只能有一个
			//内置类型也可以有默认构造,有了模板之后必须得去兼容
			//问题2,匿名对象生命周期是在这一行 因为这一行之后没人会用它了 但是const & 会延长匿名对象生命周期 到引用对象的域结束
			//匿名对象,临时对象都具有常性,所以必须得加const
			/*:_start(nullptr),
			_finsh(nullptr),
			_end_of_storage(nullptr)*/
		{
			reserve(n);
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}
		}
		//解决方案二,提供一份重载的版本
		vector(int n, const T& val = T())
		{
			reserve(n);
			for (int i = 0; i < n; i++)
			{
				push_back(val);
			}
		}
		//语法,类模板的成员函数又可以是模板
		//[first,last)
		template 
		//vector v1(10, 6);  这里inputiterator推演成int int后面解引用报错
		vector(InputIterator first, InputIterator last)//如果直接用iterator初始化就写死了必须得用vector迭代器初始化
		//只要类型符合(一致或者隐式类型转)
			/*:_start(nullptr),
			_finsh(nullptr),
			_end_of_storage(nullptr)*/
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}
		vector(const vector& v)
		{
			//reserve(v.capacity());
			/*for (auto e : v)
			{
				push_back(e);
			}*/
			_start = new T[v.capacity()];//拷贝构造虽然先开一块独立空间,但是memcpy是浅拷贝,_str都指向同一块空间,会报错
			//memcpy(_start, v._start, sizeof(T) * v.size());
			for (size_t i = 0; i < v.size(); i++)
			{
				_start[i] = v._start[i];//string的赋值会开一样大的空间拷贝数组
			}
			_finsh = _start + v.size();
			_end_of_storage = _start + v.capacity();

		}
		~vector()
		{
			delete[] _start;
			_start = _finsh = _end_of_storage = nullptr;
		}
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finsh;
		}
		const_iterator begin() const
		{
			return _start;
		}
		const_iterator end() const
		{
			return _finsh;
		}
		void push_back(const T& x)
		{
			if (_finsh == _end_of_storage)
			{
				reserve(capacity() == 0 ? 4 : 2 * capacity());		
			}
			*_finsh = x;
			_finsh++;
		}
		void pop_back()
		{
			assert(!empty());
			_finsh--;
		}
		bool empty()
		{
			return _start == _finsh;
		}
		void resize(int n, T val = T())
		{
			if (n < size())
			{
				_finsh = _start + n;
			}
			else
			{
				if (n > capacity())
				{
					reserve(n);
				}
				while (_finsh != _start + n)
				{
					*_finsh = val;
					++_finsh;
				}
			}
		}
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				//方法二.提前把size记录下来
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					//memcpy(tmp, _start, sizeof(T) * sz);//深层次的浅拷贝问题
					for (size_t i = 0; i < size(); i++)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}
				/*_start = tmp;
				_finsh = tmp + size();*///此方法错误 _finsh = _start+_finsh-_start = 0;
				//方法一,交换位置
				/*_finsh = tmp + size();
				_start = tmp;*/
				_start = tmp;
				_finsh = _start + sz;
				_end_of_storage = tmp + n;
			}
		}
		T& operator[](size_t pos)
		{
			assert(pos < size());
			return _start[pos];
		}
		const T& operator[](size_t pos) const
		{
			assert(pos < size());
			return _start[pos];
		}
		size_t capacity() const
		{
			return _end_of_storage - _start;
		}
		size_t size() const
		{
			return _finsh - _start;
		}
		
		iterator insert(iterator pos, const T& val)
		{
			assert(pos >= _start);
			assert(pos <= _finsh);
			if (_finsh == _end_of_storage)//可能会存在迭代器失效的问题 扩容后pos成立野指针
			{
				size_t len = pos - _start;
				reserve(capacity() == 0 ? 4 : 2 * capacity());
				//扩容后更新pos,解决pos失效
				pos = _start + len;
			}
			iterator end = _finsh - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				end--;
			}
			*pos = val;
			_finsh++;
			return pos;
		}
		iterator erase(iterator pos)//返回的是删除位置的下一个位置
		{
			assert(pos >= _start);
			assert(pos < _finsh);
			iterator start = pos + 1;
			while (start != _finsh)
			{
				*(start - 1) = *start;
				start++;
			}
			_finsh--;
			return pos;//其实还是pos
		}
	private:
		//c++11规定,我们可以给缺省值初始化初始化列表
		iterator _start = nullptr;
		iterator _finsh = nullptr;
		iterator _end_of_storage = nullptr;
	};
	void func(const vector& v)
	{
		for (size_t i = 0; i < v.size(); i++)
		{
			cout << v[i] << " ";
		}
		cout << endl;
		vector::const_iterator it = v.begin();
		while (it != v.end())
		{
			cout << *it << " ";
			it++;
		}
		cout << endl;
	}
	void test_vector1()
	{
		vector v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);
		/*for (size_t i = 0; i < v1.size(); i++)
		{
			cout << v1[i] << " ";
		}
		cout << endl;*/
		v1.pop_back();
		v1.pop_back();
		v1.pop_back();
		vector::iterator it = v1.begin();
		while (it != v1.end())
		{
			cout << *it << " ";
			it++;
		}
		cout << endl;
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
		func(v1);
	}
	//template
	//void f()//函数模板
	//{
	//	T x = T();//T调用构造函数构造函数生成匿名对象
	//	cout << x << endl;
	//}
	//void test_vector2()
	//{
	//	//匿名对象格式  类名();  匿名对象调用构造函数,生命周期在当前行
	//	//A a1;
	//	//a1.print();
	//	//A().print();
	//	//内置类型没有构造函数,但是有了模板就不一样了
	//	/*f();
	//	f();
	//	f();*/
	//	//定位new格式  Time* b1 = new(buff_prev) Time(6); 从地址buff_prev中初始化一个Time类型的*b1对象,初始值为6
	//}
	void test_vector2()
	{
		vector v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);
		cout << v1.size() << endl;
		cout << v1.capacity() << endl;
		v1.resize(10);
		cout << v1.size() << endl;
		cout << v1.capacity() << endl;
		func(v1);
		v1.resize(3);
		func(v1);


	}
	void test_vector3()
	{
		//vector v1;
		//v1.push_back(1);
		//v1.push_back(2);
		//v1.push_back(3);
		//v1.push_back(4);
		//v1.push_back(5);
		//func(v1);	
		//auto pos = find(v1.begin(), v1.end(), 3);
		//if(pos != v1.end())
		//{
		//	pos = v1.insert(pos, 20);
		//}
		//func(v1);
		//迭代器失效问题其二
		//一种没有发生扩容,但是pos意义变了,想对3这个位置++ 加的是20
		//(*pos)++;
		//func(v1);

		vector v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		//v1.push_back(5);
		func(v1);
		auto pos = find(v1.begin(), v1.end(), 3);
		if (pos != v1.end())
		{
			//解决方案,如果引用传参是不行的,pos如果是v1.begin(),其返回值是值,也就是先拷贝一个临时对象,临时对象具有常性
			//接收这个返回值,指向这个新插入的位置
			pos = v1.insert(pos, 20);
		}//一种是扩了容,里面更新了pos,外面地址还是之前的
		func(v1);
		(*pos)++;//insert里的pos不是输出形参数
		func(v1);
		//最好就是我们认为insert后pos失效了,不能再使用
	}
	void test_vector4()
	{
		vector v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		auto pos = find(v1.begin(), v1.end(), 4);
		if (pos != v1.end())
		{
			pos = v1.erase(pos);
		}
		func(v1);
		//现在访问pos,pos不是合法位置
		//(*pos)++;//erase之后pos不能访问,行为未定义*/
	}
	void test_vector5()
	{
		vector v1;
		v1.push_back(10);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(40);

		vector::iterator it = v1.begin();
		while(it != v1.end())
		{
			if (*it % 2 == 0)
			{
				it = v1.erase(it);
			}
			//++it;//这里往前覆盖偶数后it往后移,此时it原本的位置没有判断,还有可能会越过_finsh(1,2,3,4)
			//erase后it已经不是指向原来那个值了,存在迭代器失效问题
			else//没失效正常++就行
			{
				it++;
			}
		}
		func(v1);
	}
	void test_vector6()
	{
		vector v1(10, 6);
		//vector v1(10u, 6);//解决方案一.加个u成无符号,不会匹配到inputiterator
		func(v1);
		//vector v2(++v1.begin(), --v1.end());
		//vector v2(v1.begin()+1, v1.end()-1);//返回值是值传递,拷贝成临时对象,临时对象具有常性
		//func(v2);
		std::string s("hello");
		vector v3(s.begin(), s.end());
		func(v3);//104 101 108 108 111
		int a[] = { 10,20,30 };
		vector v4(a, a + 3);
		func(v4);//10,20,30
		v1.insert(v1.begin(),9);
		func(v1);
		sort(v1.begin(), v1.end());
		func(v1);
	}
	void test_vector7()
	{
		vector v1(10, 6);
		vector v2(v1);
		func(v2);
		vector v3(3, "111111111111111111");
		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;
		vector v4(v3);
		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;
		v4.push_back("2222222222");
		v4.push_back("2222222222");
		v4.push_back("2222222222");
		v4.push_back("2222222222");
		for (auto e : v4)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}

你可能感兴趣的:(c++,算法,c++,数据结构)