C++之vector类的代码及其逻辑详解 (下)

1. insert()

这个就是在指定位置插入一个元素,首先计算要插入的这个位置和开头之间的距离,接着判断那个_finish 有没有碰到_endofstorage 或者_endofstorage 是不是为0,如果满足条件,那就进行扩容,然后接着重新计算距离,因为我们经过扩容了,所以可能插入的位置会不准,所以要重新计算,接着我们算一个end,这个end就是最后一个元素的位置,然后通过挪动的方式留出pos的空间,接着插入对应元素再++_finish 。

cpp 复制代码
void insert(iterator pos, const T& x)
{
	assert(pos >= _start && pos <= _finish);
	size_t len = pos - _start;
	if (_finish == _endofstorage && _endofstorage != 0)
	{
		reserve(capacity() * 2);
	}
	else
	{
		reserve(4);
	}
	pos = _start + len;
	iterator end = _finish - 1;
	while (end >= pos)
	{
		*(end + 1) = *end;
		--end;
	}
	*pos = x;
	++_finish;

}

2. reserve()

这个函数就是改变vector的capacity,同时并不像resize一样会添加或者减少元素。

首先保存当前元素数量 sz,然后动态分配大小为 n 的新内存 tmp。若原内存_start 非空,则通过循环调用元素的赋值运算符将原数据逐个复制到新内存中(而非直接使用 memcpy,避免浅拷贝问题),随后释放原内存。最后更新_start 指向新内存,_finish 指向原元素末尾的下一个位置,_endofstorage 指向新容量的末尾。若 n 不大于当前容量,则不执行任何操作。

简单来说就是新开一个扩容后数组然后把旧的赋值给他,接着直接把原来的vector的三个指针直接指向新的,从而完成替换实现reserve。

cpp 复制代码
void reserve(size_t n)
{
	if (n > capacity())
	{
		size_t sz = size();
		T* tmp = new T[n];
		if (_start)
		{
			//memcpy(tmp, _start, sizeof(T) * sz);
			for (int i = 0; i < sz; i++) 
			{
				tmp[i] = _start[i];
			}
			delete[] _start;
		}

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

3. resize()

这个函数就是改变vector的大小,如果比原来的size小,那就改变finish的位置。

如果比原来的size大,那就吧finish向后移动,并在每一个添加的位置赋值为val。

PS:这个val之所以要设计成const T& val=T(),是因为我们并不知道这个vector里面是什么类型的,在加上这个resize在stl库里面支持只给一个n,所以我们在这里就这么设计。意思是表用它的默认构造,我们在这里不用担心int这种内置类型,因为C++支持像int a=int(1)这种语法了。

cpp 复制代码
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;
		}
	}
}

4. swap()

这个的话就是交换两个vetcor里面的内容。

原理上来说的话就是通过swap两个vector里面的三个指针来实现。

cpp 复制代码
void swap(vector<T>& v)
{
	std::swap(_start, v._start);
	std::swap(_finish, v._finish);
	std::swap(_endofstorage, v._endofstorage);
}

5. capacity()

这个的话就是返回vector的capacity,因为_endofstorage和_start是指针而不是实际的大小,所以我们在这里要做减法。

cpp 复制代码
size_t capacity() const
{
	return (_endofstorage - _start);
}

6. size()

这个的话就是返回vector的size,原因的话和上面一样。

cpp 复制代码
size_t size() const
{
	return (_finish - _start);
}

7. operator[]

这个的话是运算符重载的[],简单来说就是可以通过下标的方式来对vector里面的内容进行访问。

同时在这里提供了普通版本和const版本。

cpp 复制代码
T& operator[](size_t pos)
{	
    assert(pos < size());
	return _start[pos];
}

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

8. print()

这个就是打印,通过迭代器的方式来对vector里面的内容进行打印。

cpp 复制代码
void print()
{
	for (auto e : *this)
	{
		std::cout << e << ' ';
	}
	cout << endl;
}

9. 总结

本文围绕C++中的vector容器展开了全面解析,从基础特性到具体接口操作进行了系统梳理。

首先,明确了vector的核心特性及空间结构,让读者对其底层存储有了整体认知;接着,深入讲解了vector类的关键成员与函数,包括私有成员的作用,以及构造函数(默认、拷贝、范围构造)和析构函数在对象创建与销毁时的机制;同时,详细介绍了迭代器相关的begin、end接口,以及erase、pop_back、insert等元素增删操作,reserve、resize、swap等空间与容器管理函数,还有capacity、size的获取方式;此外,还涵盖了重载的方括号运算符(用于便捷访问元素)和print方法(用于元素输出)。

通过这些内容,全面呈现了vector的使用逻辑与核心功能,帮助读者从底层原理到实际操作,完整掌握vector容器的应用。

以下是vector的完整代码:

cpp 复制代码
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace struggle
{
	template<class T>
	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(size_t n, const T& val = T())
		{
			resize(n, val);
		}

		vector(int n, const T& val = T())
		{
			resize(n, val);
		}

		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		vector(const vector<T>& v)
		{
			_start = new T[v.capacity()];
			for (size_t i = 0; i < v.size(); i++)
			{
				_start[i] = v._start[i];
			}
			_finish =_start+v.size();
			_endofstorage = _start + v.capacity();
		}

		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> v)
		{
			swap(v);
			return *this;
		}

		vector()
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{}

		~vector()
		{
			delete[] _start;
			_start = _finish = _endofstorage = 0;
		}

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					//memcpy(tmp, _start, sizeof(T) * sz);
					for (int i = 0; i < sz; i++) 
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}

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

		void push_back(const T& x)
		{
			if (_finish == _endofstorage && _endofstorage != 0)
			{
				reserve(capacity() * 2);
			}
			else
			{
				reserve(4);
			}
			*_finish = x;
			++_finish;
		}
		size_t capacity() const
		{
			return (_endofstorage - _start);
		}

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

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

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

		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 erase(iterator pos)
		{
			assert(pos >= _start && pos < _finish);
			iterator it = pos;
			while (it + 1 != _finish)
			{
				*it = *(it + 1);
				++it;
			}
			--_finish;
		}

		void pop_back()
		{
			assert(_start != _finish);
			--_finish;
		}

		void insert(iterator pos, const T& x)
		{
			assert(pos >= _start && pos <= _finish);
			size_t len = pos - _start;
			if (_finish == _endofstorage && _endofstorage != 0)
			{
				reserve(capacity() * 2);
			}
			else
			{
				reserve(4);
			}
			pos = _start + len;
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;
			++_finish;

		}

		/*void print(const vector<int>& v)
		{
			for(auto e:v)
			{
				std::cout << e << ' ';
			}
			cout << endl;
		}*/
		void print()
		{
			for (auto e : *this)
			{
				std::cout << e << ' ';
			}
			cout << endl;
		}
	private:
		iterator _start;
		iterator _finish;
		iterator _endofstorage;
	};
}
相关推荐
牟同學8 分钟前
深入理解 C++ 中的stdpriority_queue:从原理到实战的高效优先级管理
数据结构·c++·priority_queue
flashlight_hi21 分钟前
LeetCode 分类刷题:16. 最接近的三数之和
javascript·数据结构·算法·leetcode
艾莉丝努力练剑22 分钟前
【C/C++】形参、实参相关内容整理
c语言·开发语言·c++·学习
勤劳打代码39 分钟前
抽丝剥茧 —— 解析 PC 蓝牙检测
c++·flutter·客户端
Jooolin1 小时前
【C++】C++的多态是个啥,咋用的?
c++·后端·ai编程
程序猿本员1 小时前
2. cpp语法进阶
c++·后端
大熊学员1 小时前
JavaScript 基础语法
开发语言·javascript·ecmascript
乌萨奇也要立志学C++1 小时前
【C++详解】STL-set和map的介绍和使用样例、pair类型介绍、序列式容器和关联式容器
开发语言·c++·stl
黑色的山岗在沉睡1 小时前
P10480 可达性统计
数据结构·算法
yu2024111 小时前
异世界历险之数据结构世界(非递归快排,归并排序(递归,非递归))
java·数据结构·排序算法