Vector实现

读源码小技巧

0.熟悉他的功能

1.不要每一行读懂了再看下一行,这样读代码会很困难.

2.先拉框架,不要先抠细节

3.理解的时候连蒙带猜,再验证猜测

类:成员变量+成员函数

1.内置类型的默认构造

    void resize(size_t n, T val = T())
    //这里因为不知道类型,因此用一个匿名对象,调用默认构造。
    // 对于内置类型,在模板出现后,就可以理解成有了构造函数,以此来逻辑自洽

2.迭代器失效

void insert(iterator pos, const T& x)
{
	assert(pos >= _start);
	assert(pos <= _finish);

	if (_finish == _endofstorage)
	{
		size_t len = pos - _start;//扩容之后pos将会变成野指针,因此我们要记录偏移值,然后再更新pos
		reserve(capacity() == 0 ? 4 : capacity() * 2);
		pos = _start + len;
	}
	iterator end = _finish - 1;
	while (end >= pos)
	{
		*(end + 1) = *end;
		end--;
	}
	*pos = x;
	++_finish;
}

        因此我们如果定义了一个类似xxx::iterator it = begin() + n,这样的变量,在这个it传入insert之后,因为可能扩容,因此这个it就失效了,不能继续使用

        而erase同样。因为有删除操作,所以迭代器必定失效

        库里面的迭代器返回值返回的是删除部分下一个位置/插入部分下一个位置的iterator

而一些开发环境下,比如vs2019下会进行强制检查,erase以后就认为迭代器失效了,不能访问,访问就报错

3.关于string的深层浅拷贝 

 

 

        当我们对vector<string>进行创建新空间移动元素时,如果我们使用memcpy,那么会将vector每一个元素中的,(这里进行简单的举例),_size,_capacity,_str都完完全全地拷贝过来,因此新的_str指向的还是原来空间。因此内置类型使用memcpy,自定义的就不要用了。

        所以我们使用直接赋值,string的赋值是深拷贝

4.vector的实现

1.vector.h

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace myh
{
	template<class T>
	class vector
	{
		
	public:
		typedef T* iterator;//typedef也受访问限定符限制,外面要用因此要放在public
		typedef const T* const_iterator;
		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}

		const_iterator begin() const
		{
			return _start;
		}

		const_iterator end() const
		{
			return _finish;
		}

		vector()
			/*:_start(nullptr)因为已经给了缺省值,所以可以视为已经写了这块,我们就不用写
			, _finish(nullptr)
			, _endofstorage(nullptr)*/
		{}
		vector(const vector<T>& v)
			/*:_start(nullptr)
			,_finish(nullptr)
			,_endofstorage(nullptr)*/
		{
			reserve(v.capacity());
			for (auto& ch : v)
			{
				push_back(ch);
			}
		}
		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);
		}
		vector<T>& operator=(vector<T>tmp)//现代写法
		{
			swap(tmp);
			return *this;
		}
		vector(size_t n, const T val = T())
		{
			reserve(n);
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}
		}
		vector(int n, const T val = T())//用于匹配int int 的类型,让它不会去匹配vector(InputIterator first, InputIterator last)
		{
			reserve(n);
			for (int i = 0; i < n; i++)
			{
				push_back(val);
			}
		}
		template<class InputIterator>//在一个类模板里面还可以写模板函数
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}

		~vector()
		{
			delete[] _start;
			_start = _finish = _endofstorage = nullptr;
		}
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				T* tmp = new T[n];
				size_t sz = size();

				if (_start)
				{
					memcpy(tmp, _start, sizeof(T) * sz);
					delete[] _start;
				}

				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}

		void resize(size_t n, T val = T())
		//这里因为不知道类型,因此用一个匿名对象,调用默认构造。
		// 对于内置类型,在模板出现后,就可以理解成有了构造函数,以此来逻辑自洽
		//void resize(size_t n, const T& val = T())
		{
			if (n <= size())
			{
				_finish = _start + n;
			}
			else
			{
				reserve(n);
				while (_finish < _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
		}
		void push_back(const T& x)
		{
			if (_finish == _endofstorage)
			{
				reserve(capacity() == 0 ? 4 : capacity() * 2);
			}
			*_finish = x;
			++_finish;
		}
		void insert(iterator pos, const T& x)
		{
			assert(pos >= _start);
			assert(pos <= _finish);

			if (_finish == _endofstorage)
			{
				size_t len = pos - _start;//扩容之后pos将会变成野指针,因此我们要记录偏移值,然后再更新pos
				reserve(capacity() == 0 ? 4 : capacity() * 2);
				pos = _start + len;
			}
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				end--;
			}
			*pos = x;
			++_finish;
		}
		iterator erase(iterator pos)
		{
			assert(pos >= _start);
			assert(pos < _finish);

			iterator it = pos + 1;
			while (it < _finish)
			{
				*(it - 1) = *it;
				++it;
			}
			--_finish;
			return pos;
		}
		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()
		{
			return _endofstorage - _start;
		}

		size_t size()
		{
			return _finish - _start;
		}

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

		size_t capacity() const
		{
			return _endofstorage - _start;
		}
	private:
		iterator _start = nullptr;//为了避免重复,我们在这边先把缺省值给上
		iterator _finish = nullptr;
		iterator _endofstorage = nullptr;
	};
	void test1()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		for (size_t i = 0; i < v.size(); i++)
		{
			cout << v[i] << " ";
		}
		cout << endl;

		vector<int>::iterator it = v.begin();
		while (it != v.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;

		for (auto ch : v)
		{
			cout << ch << " ";
		}
		cout << endl;
	}
	void test2()
	{
		int i = 0;//int 也看成一个对象,这样cpp中模板的模块才能逻辑自洽
		int j(1);
		int k = int(2);

		vector<int> v;
		v.resize(10);

		vector<int*> v1;
		v1.resize(10);

		vector<string>v2;
		v2.resize(10);

		for (auto ch : v)//用于建议int里面默认构造出的是否都是0
		{
			cout << ch << " ";
		}
		for (auto ch : v1)//用于检验int*里面默认构造出的的是否都是空指针
		{
			cout << ch << " ";
		}

		cout << endl;
		for (auto ch : v2)
		{
			cout << ch << " ";
		}
	}
	void test3()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		for (size_t i = 0; i < v.size(); i++)
		{
			cout << v[i] << " ";
		}
		cout << endl;

		v.insert(v.begin(), 55);
		for (size_t i = 0; i < v.size(); i++)
		{
			cout << v[i] << " ";
		}
		cout << endl;
	}

	void test4()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		for (size_t i = 0; i < v.size(); i++)
		{
			cout << v[i] << " ";
		}
		cout << endl;

		v.erase(v.begin());
		for (size_t i = 0; i < v.size(); i++)
		{
			cout << v[i] << " ";
		}
		cout << endl;
	}
	void test5()
	{
		vector<int> v;
		vector<int> v1;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		for (size_t i = 0; i < v.size(); i++)
		{
			cout << v[i] << " ";
		}
		cout << endl;

		v1 = v;
		for (size_t i = 0; i < v1.size(); i++)
		{
			cout << v1[i] << " ";
		}
		cout << endl;
	}
	void test6()
	{
		vector<int> v1(10,1);
		vector<int> v2(v1.begin(), v1.end());

		string str("hello myh");
		vector<char> v3(str.begin(), str.end());

		for (size_t i = 0; i < v2.size(); i++)
		{
			cout << v2[i] << " ";
		}
		cout << endl;

		for (size_t i = 0; i < v3.size(); i++)
		{
			cout << v3[i] << " ";
		}
		cout << endl;
	}
}

2.test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include"vector.h"
int main()
{ 
	//myh::test1();
	//myh::test2();
	//myh::test3();
	//myh::test4();
	//myh::test5();
	myh::test6();
	return 0;
}

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值