C++ vector的模拟实现

一 vector的大致框架

1.1 框架

 vector的成员变量不再是我们熟悉的size,capacity,而是变成了功能一致的三个指针:_start,_finish,_endofstorage,三个指针的作用如下:

C++ vector的模拟实现_第1张图片

同时,因为其本身指针的特性,其迭代器也是返回其内部的指针就可以了,因此我们可以直接定义迭代器。

 大致框架如下:
 

namespace My
{
	template
	class vector
	{
	public:
        typedef T* iterator;
        typedef const T* const_iterator;
	private:
		iterator _start;
		iterator _finish;
		iterator _endofstorage;
	};
}

1.2 默认构造函数 

 实际上,我们可以在底层初始化给三个指针都赋值为nullptr,这样默认构造就可以什么都不敢,并且在初始化时就全都赋值为nullptr,可以使代码更加简练。

代码如下:
 

	//构造函数
	vector() {
	}
private:
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _endofstorage = nullptr;

1.3 析构函数

delete掉空间,将三个指针再次赋值为nullptr即可。

 

	//析构 
	~vector() {
		delete[] _start; //注意一定要加[],因为有可能存的值是一个数组
		_start = _finish = _endofstorage = nullptr;
	}

二 vector的容量操作

2.1 size函数

 一般的容器,我们都有size和capacity两个函数 来获取其容器大小,在vector中我们也有这两个函数,这里我们通过 指针-指针的差值来 计算其实际值。

 代码如下:
 

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

2.2 capacity函数

 代码如下:

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

2.3 reserve函数

  在库中,reserve 修改容量时,size 是不会发生变化的(因为有效元素个数不变),若空间容量扩大则 capacity 会相应的进行扩大,若空间容量缩小时 capacity 是不会发生变化的。

  reserve的思想就是把原来的空间舍弃掉,重新开一段大空间

代码如下:
 

	//扩容
	void reserve( size_t n) {
		if (n > capacity()) {
			//开始扩容
			T* tmp = new T[n];
			size_t sz = size();//提前算出size(),用来把原值赋值给新空间
			if (_start) {
				for (size_t i = 0; i < sz; i++) {
					tmp[i] = _start[i];
				}
				delete[] _start;//避免内存泄漏
			}
			//指针指向新空间
			_start = tmp;
			_finish = _start + sz;
			_endofstorage = _start + n;
		}
	}

2.4 resize函数

 resize 修改有效元素个数时,size 会进行相应的扩大或缩小变化,capacity 不一定会变化(有效元素增多时,若容量足够则capacity不变,否则会扩容;有效元素减少时,capacity 不变)

 resize的两个操作如下:

  • 1.如果n小于当前的size,则数据个数缩小到n
  • 2.如果n大于于当前的size,则说明空间不够需要增容,并且将size扩大到n

  注意,这里val得用T的默认构造。 

 代码示例:

	//resize
	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;
			}
		}
	}

三迭代器 

  vector的迭代器就是原生指针,因此直接返回指针即可:
 

typedef T* iterator;
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;
}

四 元素修改函数

4.1 insert函数

 在指定pos位置进行插入元素

 但是这里却有一个很坑的点,那就是不小心写出来的代码就会引起迭代器失效的问题。

  因为插入后,我们可能会发生扩容,pos指针会失效,这里我们先记录一下pos位置和起始位置的差值,扩容后让pos指针指向新空间。

	void insert(iterator pos, const T& val) {
		assert(pos >= _start);
		assert(pos <= _finish);
		if (_finish == _endofstorage) {
			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;
	}

但要注意,这样的话,外部的pos指针怎么办呢?

这里是值传递,形参的改变是不会改变实参的,所以说外面的pos依旧没有实现更新操作,依旧会失效。

正确写法是通过返回值去解决问题的,返回的是迭代器,即新插入元素的位置。

正确代码为:
 

	iterator insert(iterator pos, const T& val) {
		assert(pos >= _start);
		assert(pos <= _finish);
		if (_finish == _endofstorage) {
			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;
	}

4.2 erase()

  这里主要的就是从后往前删除的,这点需要大家注意一下。

  同时,erase也会发生迭代器失效问题,因此要返回值避免迭代器失效。

代码如下:
 

	iterator erase(iterator pos) {
		assert(pos >= _start);
		assert(pos < _finish);
		iterator it = pos + 1;
		while (it < _finish) {
			*(it - 1) = *it;
			++it;
		}
		--_finish;
		return pos;
	}

4.3 push_back()

插入尾部元素,直接复用insert.

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

4.4 pop_back() 

删除尾部元素,直接把_finish--就好。

	void pop_back()
	{
		assert(_start); //注意判空
		--_finish;
	}

五 元素访问

 5.1 []的重载

  直接放回数组中的数据即可

	T& operator[](size_t pos) {
		assert(pos < size());
		return _start[pos];
	}

	const T& operator[](size_t pos) const {
		assert(pos < size());
		return _start[pos];
	}

六 其它函数 

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()) {
	reserve(n);
	for (int i = 0; i < n; i++) {
		push_back(val);
	}
}

//区间构造
template 
vector(InputIterator first, InputIterator last) {
	while (first != last) {
		push_back(*first);
		++first;
	}
}

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

//拷贝构造
vector(const vector& v) {
	reserve(v.capacity());
	for (auto& x : v) {
		push_back(x);
	}
}

//移动构造
vector(vector&& v) {
	swap(v);
}

//赋值重载
vector& operator=(const vector& v) {
	vector tmp(v);
	swap(tmp);
	return *this;
}
//移动赋值
vector& operator=(vector&& v) {
	swap(v);
	return *this;
}

七 完整代码和测试代码

 

#pragma once
#include
#include

using namespace std;

namespace My {

	template
	class vector {
	public:
		typedef T* iterator;
		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() {
		}


		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()) {
			reserve(n);
			for (int i = 0; i < n; i++) {
				push_back(val);
			}
		}

		//区间构造
		template 
		vector(InputIterator first, InputIterator last) {
			while (first != last) {
				push_back(*first);
				++first;
			}
		}

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

		//拷贝构造
		vector(const vector& v) {
			reserve(v.capacity());
			for (auto& x : v) {
				push_back(x);
			}
		}

		//移动构造
		vector(vector&& v) {
			swap(v);
		}

		//赋值重载
		vector& operator=(const vector& v) {
			vector tmp(v);
			swap(tmp);
			return *this;
		}
		//移动赋值
		vector& operator=(vector&& v) {
			swap(v);
			return *this;
		}

		//扩容
		void reserve( size_t n) {
			if (n > capacity()) {
				//开始扩容
				T* tmp = new T[n];
				size_t sz = size();//提前算出size(),用来把原值赋值给新空间
				if (_start) {
					for (size_t i = 0; i < sz; i++) {
						tmp[i] = _start[i];
					}
					delete[] _start;//避免内存泄漏
				}
				//指针指向新空间
				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}

		//resize
		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;
				}
			}
		}

		iterator insert(iterator pos, const T& val) {
			assert(pos >= _start);
			assert(pos <= _finish);
			if (_finish == _endofstorage) {
				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 push_back(const T& val) {
			insert(end(), val);
		}

		iterator erase(iterator pos) {
			assert(pos >= _start);
			assert(pos < _finish);
			iterator it = pos + 1;
			while (it < _finish) {
				*(it - 1) = *it;
				++it;
			}
			--_finish;
			return pos;
		}
		void pop_back()
		{
			assert(_start); //注意判空
			--_finish;
		}

		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 _endofstorage - _start;
		}

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


		//析构 
		~vector() {
			delete[] _start; //注意一定要加[]
			_start = _finish = _endofstorage = nullptr;
		}

	private:
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _endofstorage = nullptr;

	};


	void test_vector1()
	{
		vector 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::iterator it = v.begin();
		while (it != v.end())
		{
			*it *= 10;
			cout << *it << " ";
			++it;
		}
		cout << endl;

		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test_vector2()
	{
		int i = 0;
		int j(1);
		int k = int(2);

		vector v1;
		v1.resize(10);

		vector v2;
		//v2.resize(10, string("xxx"));
		v2.resize(10, "xxx");

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test_vector3()
	{
		vector v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		v.push_back(6);
		v.push_back(7);

		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;

		vector::iterator it = v.begin() + 2;
		v.insert(it, 30);
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;

		//v.insert(v.begin(), 30);
		v.insert(v.begin() + 3, 30);
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test_vector4()
	{
		vector v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		v.push_back(6);
		v.push_back(7);

		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;

		auto pos = v.begin();
		v.erase(pos);

		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;

		v.erase(v.begin() + 3);
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	//void test_vector5()
	//{
	//	// 1 2 3 4 5
	//	// 1 2 3 4 5 6
	//	// 2 2 3 4 5
	//	std::vector v;
	//	v.push_back(1);
	//	v.push_back(2);
	//	v.push_back(3);
	//	v.push_back(4);
	//	v.push_back(5);
	//	//v.push_back(6);

	//	for (auto e : v)
	//	{
	//		cout << e << " ";
	//	}
	//	cout << endl;

	//	auto it = v.begin();
	//	while (it != v.end())
	//	{
	//		// vs2019进行强制检查,erase以后认为it失效了,不能访问,访问就报错
	//		if (*it % 2 == 0)
	//		{
	//			v.erase(it);
	//		}

	//		++it;
	//	}

	//	for (auto e : v)
	//	{
	//		cout << e << " ";
	//	}
	//	cout << endl;
	//}

	void test_vector5()
	{
		//std::vector v;
		vector v;

		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(4);
		v.push_back(5);
		v.push_back(6);

		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;

		auto it = v.begin();
		while (it != v.end())
		{
			if (*it % 2 == 0)
			{
				it = v.erase(it);
			}
			else
			{
				++it;
			}
		}

		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test_vector6()
	{
		vector v;
		v.push_back("111111111111111111111");
		v.push_back("111111111111111111111");
		v.push_back("111111111111111111111");
		v.push_back("111111111111111111111");
		v.push_back("111111111111111111111");


		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
	}


	void test_vector7()
	{
		vector v1;
		v1.push_back(1);
		v1.push_back(1);
		v1.push_back(1);
		v1.push_back(1);
		v1.push_back(1);

		vector v2(v1);

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;

		vector v3;
		v3.push_back(10);
		v3.push_back(20);
		v3.push_back(30);
		v3.push_back(40);

		v1 = v3;

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test_vector8()
	{
		//vector v0(10, 0);
		vector v1(10, "xxxx");

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		vector v2;
		v2.push_back(10);
		v2.push_back(20);
		v2.push_back(30);
		v2.push_back(40);

		vector v3(v2.begin(), v2.end());

		string str("hello world");
		vector v4(str.begin(), str.end());
		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;

		for (auto e : v4)
		{
			cout << e << " ";
		}
		cout << endl;
	}


}

你可能感兴趣的:(c++,开发语言,java,算法,数据结构)