C++ vector 的模拟实现


vector 各函数接口总览

template <class T>
class vector {
public:
	typedef Iterator<T, T&, T*> iterator;
	typedef Iterator<T, const T&, const T*> const_iterator;
	typedef Reverse_Iterator<iterator, T&, T*> reverse_iterator;
	typedef Reverse_Iterator<const_iterator, const T&, const T*> const_reverse_iterator;
 
	//默认成员函数
	vector<T>();
	vector<T>(size_t n, const T& val = T());
	vector<T>(int n, const T& val = T());
	vector<T>(long n, const T& val = T());
	template <typename InputIterator>
	vector<T>(InputIterator first, InputIterator last);
	vector(const vector<T>& vtr);
	vector<T>& operator=(const vector<T>& vtr);
	~vector();

	//容量和大小相关函数
	size_t size()const;
	size_t capacity()const;
	void resize(size_t n, const T& val = T());
	void reserve(size_t n);
	bool empty()const;

	//迭代器相关函数
	iterator begin();
	iterator end();
	const_iterator begin()const;
	const_iterator end()const;
	const_iterator cbegin()const;
	const_iterator cend()const;
	reverse_iterator rbegin();
	reverse_iterator rend();
	const_reverse_iterator rbegin()const;
	const_reverse_iterator rend()const;
	const_reverse_iterator crbegin()const;
	const_reverse_iterator crend()const;

	//修改容器相关函数
	void push_back(const T& val);
	void pop_back();
	iterator erase(iterator pos);
	iterator erase(iterator first, iterator last);
	iterator insert(iterator pos, const T& val);
	iterator insert(iterator pos, size_t n, const T& val);
	template<typename InputIterator>
	iterator insert(iterator pos, InputIterator first, InputIterator last);

	//访问容器相关函数
	T& operator[](size_t pos);
	const T& operator[](size_t pos)const;
	T& at(size_t pos);
	const T& at(size_t pos)const;
	T& front();
	const T& front()const;
	const T& back();
	const T& back()const;

	//其他函数
	void swap(vector<T>& vtr);
	T* data();
	const T* data()const;
private:
	T* _start;
	T* _finish;
	T* _end_of_storage;
};

🌸注:

  1. 为了防止与标准库中的 vector 命名冲突,所以需要将我们自己实现的 vector 放到自己的命名空间中
  2. 所有的 vector 成员函数默认在类内定义,在类外实现
  3. vector 中的容器为三个指针,其分别指向容器的不同位置,如下图:
    ## 图片
  4. 上图中,_start 指向容器中第一个元素,_finish 指向容器中最后一个元素的下一个位置,_end_of_storage 指向容器最后一个空间的下一个位置

一、默认成员函数

构造函数

构造函数1

🌸注:模板类的成员函数在类外实现时,需要声明类的模板

template <typename T>	//声明类的模板
vector<T>::vector() 
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr) 
{}

构造函数2

🌸注:模板类的成员函数为模板函数时,如果该模板函数需要在模板类外实现,那么需要先声明类模板,然后声明函数模板。然后再写函数实现

template <class T>		//类模板
template <typename InputIterator>	//函数模板
vector<T>::vector(InputIterator first, InputIterator last) {
	while (first != last) {
		push_back(*first);
		first++;
	}
}

构造函数3
template <typename T>
vector<T>::vector(size_t n, const T& val) {
	reserve(n);
	for (size_t i = 0; i < n; i++) {
		_start[i] = val;
	}
	_finish = _start + n;
}

❗️注意:

  1. 该构造函数知道其需要用于存储 n 个数据的空间,所以最好用 reserve 函数一次性开辟好空间,避免插入元素时需要增容多次,导致效率降低

  2. 如果只实现上述一种情况就会发生下面的问题:

int main() {
	yw::vector<int> vtr(5, 10);		//error
}

🌸原因:因为编译器运行 vtr(5, 10) 时,会优先跟第二个构造函数的模板匹配

//第二个构造函数
template <typename InputIterator>
vector<T>::vector(InputIterator first, InputIterator last)

🌸解决方案:构造函数三再实现两个重载函数

template <typename T>
vector<T>::vector(int n, const T& val) {
	reserve(n);
	for (size_t i = 0; i < n; i++) {
		_start[i] = val;
	}
	_finish = _start + n;
}

template <typename T>
vector<T>::vector(long n, const T& val) {
	reserve(n);
	for (size_t i = 0; i < n; i++) {
		_start[i] = val;
	}
	_finish = _start + n;
}

拷贝构造函数
  1. 老版写法
template <typename T>
vector<T>::vector(const vector<T>& vtr) {
	_start = new T[vtr.capacity()];
	_finish = _start + vtr.size();
	_end_of_storage = _start + vtr.capacity();
	for (size_t i = 0; i < size(); i++) {
		_start[i] = vtr[i];
	}
}

分析下面的拷贝构造函数写法是否正确:

template <typename T>
vector<T>::vector(const vector<T>& vtr) {
	_start = new T[vtr.capacity()];
	_finish = _start + vtr.size();
	_end_of_storage = _start + vtr.capacity();
	memcpy(_start, vtr._start, sizeof(T) * vtr.size());
}

🌸上面使用 memcpy 函数拷贝的写法是错误的,因为 memcpy 是按字节拷贝,所以当 vector 容器中存放的是 string 类型时,其拷贝只会拷贝 string 中的指针,而不会拷贝整个字符串,如下图:

在这里插入图片描述

🌸此时我们发现两个容器中的 string 指向同一块内存,这就是浅拷贝(memcpy)造成的后果。当我们删除一个容器时,另一个容器中的 string 元素也会失效

🌸总结:

  1. 如果 vector 当中存储的元素类型是内置类型(int)或浅拷贝的自定义类型(Date),使用 memcpy 函数进行进行拷贝构造是没问题的

  2. 但如果 vector 当中存储的元素类型是深拷贝的自定义类型(string),则使用 memcpy 函数将不能达到我们想要的效果

🌸老版写法避免深浅拷贝问题的方法:

for (size_t i = 0; i < size(); i++) {
		_start[i] = vtr[i];		//这里会调用容器元素的 operator=,避免了浅拷贝问题
}
  1. 新版写法
template <typename T>
vector<T>::vector(const vector<T>& vtr) {
	reserve(vtr.capacity());
	for (auto e : vtr) {
		push_back(e);
	}
}

❗️注意: 在使用范围 for 对容器 vtr 进行遍历的过程中,变量 e 就是每一个数据的拷贝,然后将 e 尾插到构造出来的容器当中。就算容器 vtr 当中存储的数据是 string 类,在 e 拷贝时也会自动调用 string 的拷贝构造(深拷贝),所以也能够避免出现与使用 memcpy 时类似的问题


赋值运算符重载

🌸赋值运算符重载也涉及深浅拷贝的问题,这里提供两种写法:

  1. 传统写法
template <typename T>
vector<T>& vector<T>::operator=(const vector<T>& vtr) {
	if(this != &vtr) {
		delete[] _start;
		_start = new T[vtr.capacity()];
		_finish = _start + vtr.size();
		_end_of_storage = _start + vtr.capacity();
		for (size_t i = 0; i < size(); i++) {
			_start[i] = vtr[i];
		}
	}
	return *this;	
}

❗️注意:这里和拷贝构造一样,不能使用 memcpy 函数进行拷贝

  1. 新版写法
template <typename T>
vector<T>& vector<T>::operator=(const vector<T>& vtr) {
	if (&vtr != this) {
		vector<T> tmp = vtr;
		swap(tmp);
	}
	return *this;
}

析构函数

template <typename T>
vector<T>::~vector() {
	if (_start != nullptr) {
		delete[] _start;
		_start = _finish = _end_of_storage = nullptr;
	}
}

二、容量和大小相关函数

size() 和 capacity()

template <typename T>
size_t vector<T>::size()const {
	return _finish - _start;
}

template <typename T>
size_t vector<T>::capacity()const {
	return _end_of_storage - _start;
}

reserve()

template <typename T>
void vector<T>::reserve(size_t n) {
	if (capacity() < n) {
		T* tmp = new T[n];
		size_t len = size();
		for (size_t i = 0; i < size(); i++) {
			tmp[i] = _start[i];
		}
		delete[] _start;
		_start = tmp;
		_finish = _start + len;
		_end_of_storage = _start + n;
	}
}

❗️注意:

  1. 在进行操作之前需要提前记录当前容器当中有效数据的个数。因为我们最后需要更新 _finish 指针,而 _finish = _start + size(),当 _start 指针的指向改变后,我们再调用 size(),通过 _finish - _start 计算出的有效数据的个数就是一个随机值了

  2. 不能使用 memcpy 函数拷贝容器当中的元素

提问:当 vector 当中存储的是 string 的时候,虽然使用 memcpy 函数 reserve 出来的容器与原容器当中每个对应的 string 成员都指向同一个字符串空间,但是原容器存储数据的空间不是已经被释放了,相当于现在只有一个容器维护这这些字符串空间,为什么不能用 memcpy 呢?

答:在使用 memcpy 前,会 delete 原容器中的元素,此时原容器当中存储的 string 在释放时会调用其析构函数,将其指向的字符串也进行释放,所以使用 memcpy 函数 reserve 出来的容器当中的每一个 string 所指向的字符串实际上是一块已经被释放的空间,访问该容器时就是对内存空间进行非法访问


resize()

template <typename T>
void vector<T>::resize(size_t n, const T& val) {
	if (capacity() < n) {
		reserve(n);
	}
	if (size() > n)
		_finish = _start + n;
	else {
		for (size_t i = 0; i < n - size(); i++) {
			*(_finish++) = val;
		}
	}
}

empty()

template <typename T>
bool vector<T>::empty()const {
	return _start == _finish;
}

三、迭代器相关函数

🌸如果只要实现正向迭代器,那么很简单,将容器中存放数据的指针重命名为迭代器的形式即可,因为 vector 的迭代器就是一个容器相应数据的指针:

//只实现正向迭代器写法
template <class T>
class {
public:
	//...
	typedef T* iterator;
	typedef const T* const_iterator;
	iterator begin();
	iteartor end();
	const_iterator begin()const;
	const_iterator end()const;
	const_iterator cbegin()const;
	const_iterator cend()const;
};

🌸但是如果我们既想要实现正向迭代器,又想要实现反向迭代器,那上面的方法就失效了,下面介绍同时实现正向和反向迭代器的方法:

  1. 正向迭代器和上面写法不变,将返向迭代器封装成一个类

  2. 将正向迭代器封装成一个类,而反向迭代器作为正向迭代器的一个适配器(推荐)


写法一

//将反向迭代器封装成一个类
template <class T, class Ref, class Ptr>
class Reverse_Iterator {
	typedef Reverse_Iterator<T, Ref, Ptr> self;

	Reverse_Iterator(T* it)
		:_it(it)
	{}
	self& operator++() {
		_it--;
		return *this;
	}
	self operator++(int) {
		self tmp(_it—-);
		return tmp;
	}
	self& operator-() {
		_it++;
		return *this;
	}
	self operator-(int) {
		self tmp(_it++);
		return tmp;
	}
	Ref operator*() {
		return *_it;
	}
	Ptr operator->() {
		return _it;
	}
	bool operator==(const self& it) {
		return _it == it._it;
	}
	bool operator!= (const self & it) {
		return _it != it._it;
	}
private:
	T* _it;
};

template<class T>
class vector {
public:
	typedef T* iterator;
	typedef const T* const_iterator;
	typedef Reverse_Iterator<T, T&, T*> reverse_iterator;
	typedef Reverse_Iterator<T, const T&, const T*> const_reverse_iterator;

	iterator begin() {
		return _start;
	}
	iterator end() {
		return _finish;
	}
	const_iterator begin()const {
		return _start;
	}
	const_iterator end()const {
		return _finish;
	}
	const_iterator cbegin()const {
		return _start;
	}
	const_iterator cbegin()const {
		return _finish;
	}
	reverse_iterator rbegin() {
		return reverse_iterator(_finish - 1);
	}
	reverse_iterator rend() {
		return reverse_iterator(_start - 1);
	}
	const_reverse_iterator rbegin()const {
		return const_reverse_iterator(_finish - 1);
	}
	const_reverse_iterator rend()const {
		return const_reverse_iterator(_start - 1);
	}
	const_reverse_iterator crbegin()const {
		return const_reverse_iterator(_finish - 1);
	}
	const_reverse_iterator crend()const {
		return const_reverse_iterator(_start - 1);
	}
	//其他函数...
private:
	T* _start;
	T* _finish;
	T* _end_of_storage;
};

写法二

//正向迭代器
template <class T, class Ref, class Ptr>
struct Iterator {
	typedef Iterator<T, Ref, Ptr> self;

	//模板构造函数写法
	//Iterator(T* it) :_it(it) {};		//也可以
	Iterator<T, Ref, Ptr>(T* it) :_it(it) {};
	
	//self(T* it) :_it(it) {};		//error,构造函数名字必须与类名相同

	self& operator++() {	//前置 ++
		_it++;
		return *this;
	}
	self operator++(int) {	//后置 ++
		self tmp(_it++);
		return tmp;
	}
	self& operator--() {
		_it--;
		return *this;
	}
	self operator--(int) {
		self tmp(_it--);
		return tmp;
	}
	Ref operator*() {
		return *_it;
	}
	Ptr operator->() {
		return _it;
	}
	bool operator==(const self& it) {
		return _it == it._it;
	}
	bool operator!= (const self& it) {
		return _it != it._it;
	}

	T* _it;
};

//反向迭代器
template <class Iterator, class Ref, class Ptr>
struct Reverse_Iterator {
	typedef Reverse_Iterator<Iterator, Ref, Ptr> self;

	Reverse_Iterator(Iterator it) :_it(it) {};

	self& operator++() {
		--_it;
		return *this;
	}
	self operator++(int) {
		self tmp(_it--);
		return tmp;
	}
	self& operator--() {
		++_it;
		return *this;
	}
	self operator--(int) {
		self tmp(_it++);
		return tmp;
	}
	Ref operator*() {
		return *_it;
	}
	Ptr operator->() {
		return _it;
	}
	bool operator==(const self& it) {
		return it._it == _it;
	}
	bool operator!=(const self& it) {
		return it._it != _it;
	}
	
	Iterator _it;
};

//vector 中实现的 begin() 和 end() 系列
template <class T>
class vector {
public:
	typedef Iterator<T, T&, T*> iterator;
	typedef Iterator<T, const T&, const T*> const_iterator;
	typedef Reverse_Iterator<iterator, T&, T*> reverse_iterator;
	typedef Reverse_Iterator<const_iterator, const T&, const T*> const_reverse_iterator;
 	
	//迭代器相关函数
	iterator begin();
	iterator end();
	const_iterator begin()const;
	const_iterator end()const;
	const_iterator cbegin()const;
	const_iterator cend()const;
	reverse_iterator rbegin();
	reverse_iterator rend();
	const_reverse_iterator rbegin()const;
	const_reverse_iterator rend()const;
	const_reverse_iterator crbegin()const;
	const_reverse_iterator crend()const; 

 	//其他函数...
private:
	T* _start;
	T* _finish;
	T* _end_of_storage;
};

写法说明

🌸迭代器不需要实现析构函数,因为其本身没有义务释放 vector 中的元素,这是 vector 该考虑的问题


正向迭代器 Iterator

一、正向迭代器的成员变量

  1. vector 中的迭代器就是一个指针,所以如果将正向迭代器封装成类,那么其成员变量也就是一个指向 vector 容器元素的指针,其类型为 T*

  2. 封装正向迭代器的类由 struct 定义,因为我们不需要保护其成员变量和成员函数,当然你也可以用 class 定义

template <class T, class Ref, class Ptr>
class Iterator {
public:
	//else...
private:
	T* _it;
};

二、正向迭代器的类模板参数

template <class T, class Ref, class Ptr>
strcut Iterator {
	//...
};

🌸正向迭代器的模板参数有三个:

  1. class T:表明 vector 容器中元素的数据类型

  2. class Ref:当我们对迭代器进行 " * " 操作时,需要返回容器中的元素。该模板参数表明 Iterator 类中的成员函数返回值为引用(Reference),且这个引用是 vector 容器中数据元素的引用,即 Ref == T&,例如:

//vector 类中
template <class T>
class vector {
public:
	typedef Iterator<T, T&, T*> iterator;	//说明 Ref == T&
	//...
};
//Iterator 类中
template <class T, class Ref, class Ptr>
struct Iterator {
	//返回指针 _it 对应的数据元素的引用
	Ref operator*() {
		return *_it;
	}
	//else...
	T* _it;
};
  1. class Ptr:当我们对迭代器进行 " -> " 操作时,需要返回容器元素的地址,所以该模板参数表明 Iterator 类中的成员函数返回值为指针(Pointer),并且这个指针是 vector 容器中数据元素的指针,即 Ptr == T*,例如:
//vector 类中
template <class T>
class vector {
public:
	typedef Iterator<T, T&, T*> iterator;	//说明 Ptr == T*
	//...
};
//Iterator 类中
template <class T, class Ref, class Ptr>
struct Iterator {
	//返回数据元素的指针,也就是返回 Iterator 中的成员变量 _it
	Ptr operator->() {
		return _it;
	}
	//else...
	T* _it;
};

🌸根据上面的例子我们可以知道,“->” 的重载返回的是:使用 “->” 符号时需要的指针,如果返回的指针还能使用 “->”,则会继续使用该运算符

三、typedef 的作用

🌸我们在定义实现 Iterator 中可以看到这么一行代码:

typedef Iterator<T, Ref, Ptr> self;
  1. 该代码的意思是:给自己取个别名 self

  2. 因为在迭代器中会有 ++、-- 等操作,其返回的仍是一个迭代器(对象),所以这样可以使代码更加清晰

//不使用 typedef
template <class T, class Ref, class Ptr>
struct Iterator {
	//迭代器进行 ++ 操作后返回的仍是一个迭代器
	Iterator<T, Ref, Ptr>& operator++() {
		_it++;
		return *this;
	}
	//else...
	T* _it;
}
//使用 typedef
template <class T, class Ref, class Ptr>
struct Iterator {
	typedef Iterator<T, Ref, Ptr> self;
	self& operator++() {
		_it++;
		return *this;
	}
	//else...
	T* _it;
}

四、正向迭代器的运算符重载

  1. operator++() 和 operator()-- :其本质就是迭代器中成员变量 _it 的 ++ 和 --,然后返回一个迭代器对象。注意用 int 占位符区分前置和后置
//前置 ++
self& operator++() {
	_it++;
	return *this;
}
//后置 ++
self operator++(int) {
	self tmp(_it++);
	return tmp;
}
self& operator--() {
	_it--;
	return *this;
}
self operator--(int) {
	self tmp(_it--);
	return tmp;
}
  1. operator*() 和 operator->()
Ref operator*() {
	return *_it;
}
Ptr operator->() {
	return _it;
}
  1. operator==() 和 operator!=():本质上就是成员变量 _it 的比较
bool operator==(const self& it) {
	return _it == it._it;
}
bool operator!= (const self& it) {
	return _it != it._it;
}

反向迭代器
  1. 反向迭代器就是正向迭代器的一个适配器

  2. 反向迭代器也是一个类,其成员变量为一个正向迭代器

  3. 反向迭代器通过使用正向迭代器的接口,从而实现反向迭代器的各种操作

//Reverse_Iterator 类中
template <class Iterator, class Ref, class Ptr>
struct Reverse_Iterator {
	//else...
	Iterator _it;	//成员变量为正向迭代器
};
//vector 类中
template <class T>
class vector {
public:
	typedef Iterator<T, T&, T*> iterator;
	typedef Reverse_Iterator<iterator, T&, T*> reverse_iterator;
	//else...
}

一·、反向迭代器的类模板参数

template <class Iterator, class Ref, class Ptr>
struct Reverse_Iterator {
	//else...
};

其中:

  1. class Iterator:表明第一个参数传入的是正向迭代器

❗️注意:

  1. Iterator 只是模板参数的标识符,在这里还没有实际意义

  2. 这里也可以写成 class T,其并无影响,只是写成 Iterator 能够更加形象的表明反向迭代器就是正向迭代器的适配器

  3. 并且正向迭代器(Iterator)就是反向迭代器第一个模板参数实例化时传入的参数类型

  4. 反向迭代器模板参数实例化是在 vector 中的 typedef 完成的

template <class T, class Ref, class Ptr>
struct Reverse_Iterator {
	//else...
	T _it;
};
template <class T>
class vector {
public:
	typedef Iterator<T, T&, T*> iterator;
	//反向迭代器模板参数实例化(第一个参数传入的就是正向迭代器 iterator)
	typedef Reverse_Iterator<iterator, T&, T*> iterator;	
	//else...
};
  1. class Ref:与正向迭代器功能相同

  2. class Ptr:与正向迭代器功能相同

二、typedef 的作用

🌸与正向迭代器相同,不多赘述

typedef Reverse_Iterator<Iterator, Ref, Ptr> self;

三、反向迭代器的运算符重载

🌸反向迭代器运算符重载的思路:通过调用正向迭代器的运算符重载实现反向迭代器的运算符重载,即适配器

  1. operator++() 和 operator–():通过调用正向迭代器的 ++ 和 – 实现
self& operator++() {	//前置 ++
	--_it;		//相当于 _it.operator++()
	return *this;
}
self operator++(int) {
	self tmp(_it--);
	return tmp;
}
self& operator--() {
	++_it;
	return *this;
}
self operator--(int) {
	self tmp(_it++);
	return tmp;
}
  1. operator*() 和 operator->()
Ref operator*() {
	return *(_it);	//相当于 _it.operator*()
}

Ptr operator->() {
	return _it;
}

🌸说明一下 operator->():

该函数返回的是其成员变量,即一个正向迭代器,由于该迭代器还能继续使用 “->”,所以返回的正向迭代器还会继续使用 “->” 进行运算

  1. operator==() 和 operator!=():调用正向迭代器的 == 和 !=
bool operator==(const self& it) {
	return it._it == _it;
}
bool operator!=(const self& it) {
	return it._it != _it;
}

vector 容器中

🌸定义完上面的正向迭代器和反向迭代器后,我们就可以在 vector 中 typedef 我们需要的迭代器以及其对应的名字,然后声明我们需要实现的一系列 begin 和 end 函数

template <class T>
class vector {
public:
	typedef Iterator<T, T&, T*> iterator;
	typedef Iterator<T, const T&, const T*> const_iterator;
	typedef Reverse_Iterator<iterator, T&, T*> reverse_iterator;
	typedef Reverse_Iterator<const_iterator, const T&, const T*> const_reverse_iterator;
 	
	//迭代器相关函数
	iterator begin();
	iterator end();
	const_iterator begin()const;
	const_iterator end()const;
	const_iterator cbegin()const;
	const_iterator cend()const;
	reverse_iterator rbegin();
	reverse_iterator rend();
	const_reverse_iterator rbegin()const;
	const_reverse_iterator rend()const;
	const_reverse_iterator crbegin()const;
	const_reverse_iterator crend()const; 

 	//其他函数...
private:
	T* _start;
	T* _finish;
	T* _end_of_storage;
};

❗️注意:对于 const 迭代器的写法,我们不能写成如下:

typedef const Iterator<T, T&, T*> const_iterator;	//error

🌸因为 const 迭代器本身可以进行 ++ 或 – 操作进行改变,但是其指向的值不会改变

迭代器相关函数实现
template <typename T>
//下面的 typename 的作用是说明后面的一串标识符为数据类型
//不然编译器不知道 vector<T>::iterator 是什么东西
//为什么函数参数列表和内部的 iterator 不用这样写?
//因为 vector<T>::begin() 告诉了编译器这是 vector 的成员函数,所以可以直接使用类里面 typedef 的成员
typename vector<T>::iterator vector<T>::begin() {
	return iterator(_start);
}

template <typename T>
typename vector<T>::iterator vector<T>::end() {
	return iterator(_finish);
}

template <typename T>
typename vector<T>::const_iterator vector<T>::begin()const {
	return const_iterator(_start);
}

template <typename T>
typename vector<T>::const_iterator vector<T>::end()const {
	return const_iterator(_finish);
}

template <typename T>
typename vector<T>::const_iterator vector<T>::cbegin()const {
	return const_iterator(_start);
}

template <typename T>
typename vector<T>::const_iterator vector<T>::cend()const {
	return const_iterator(_finish);
}

template <typename T>
typename vector<T>::reverse_iterator vector<T>::rbegin() {
	return reverse_iterator(iterator(_finish - 1));
}

template <typename T>
typename vector<T>::reverse_iterator vector<T>::rend() {
	return reverse_iterator(iterator(_start - 1));
}

template <typename T>
typename vector<T>::const_reverse_iterator vector<T>::rbegin()const {
	return const_reverse_iterator(const_iterator(_finish - 1));
}

template <typename T>
typename vector<T>::const_reverse_iterator vector<T>::rend()const {
	return const_reverse_iterator(const_iterator(_start - 1));
}

template <typename T>
typename vector<T>::const_reverse_iterator vector<T>::crbegin()const {
	return const_reverse_iterator(const_iterator(_finish - 1));
}

template <typename T>
typename vector<T>::const_reverse_iterator vector<T>::crend()const {
	return const_reverse_iterator(const_iterator(_start - 1));
}

四、修改容器相关函数

push_back() 和 pop_back()

template <typename T>
void vector<T>::push_back(const T& val) {
	if (size() + 1 == capacity()) {
		reserve(size() + 1);
	}
	*(_finish++) = val;
}
template <typename T>
void vector<T>::pop_back() {
	assert(size() > 0);
	_finish--;
}

insert()

template <typename T>
typename vector<T>::iterator vector<T>::insert(iterator pos, size_t n, const T& val) {
	size_t len = pos._it - _start;
	size_t cap = n + size();
	if (n + size() > capacity()) {
		reserve(n + size());
	}
	for (iterator it = end() - 1; it != pos - 1; it--) {
		*(it + n) = *it;
	}
	for (size_t i = 0; i < n; i++) {
		_start[len + i] = val;
	}
	_finish = _start + cap;
	return iterator(_start + len);
}

template <typename T>
template <typename InputIterator>
typename vector<T>::iterator vector<T>::insert(iterator pos, InputIterator first, InputIterator last) {
	size_t n = last - first;
	size_t len = pos._it - _start;
	size_t cap = n + size();
	if (n + size() > capacity()) {
		reserve(n + size());
	}
	for (iterator it = end() - 1; it != pos - 1; it--) {
		*(it + n) = *it;
	}
	for (size_t i = 0; i < n; i++) {
		_start[len + i] = *(first++);
	}
	_finish = _start + cap;
	return iterator(_start + len);
}

erase()

template <typename T>
typename vector<T>::iterator vector<T>::erase(iterator pos) {
	assert(pos._it != nullptr && pos._it < _finish);
	for (T* begin = pos._it; begin != _finish; begin++) {
		*begin = *(begin + 1);
	}
	_finish--;
	return pos,
}

template <typename T>
typename vector<T>::iterator vector<T>::erase(iterator first, iterator last) {
	assert(first._it >= _start && last._it <= _finish && last._it != nullptr);
	iterator ret = last;
	for (T* begin = last._it; begin != _finish; begin++) { 
		*(first++) = *(last++);
	}
	_finish -= (last._it - first._it);
	return ret;
}

五、访问容器相关函数

operator[ ]

template <typename T>
T& vector<T>::operator[](size_t pos) {
	assert(pos < size());
	return _start[pos];
}
template <typename T>
const T& vector<T>::operator[](size_t pos)const {
	assert(pos < size());
	return _start[pos];
}

front() 和 back()

template <typename T>
T& vector<T>::front() {
	assert(size() > 0);
	return *_start;
}
template <typename T>
const T& vector<T>::front()const {
	assert(size() > 0);
	return *_start;
}

template <typename T>
T& vector<T>::back() {
	assert(size() > 0);
	return *(_finish - 1);
}
template <typename T>
const T& vector<T>::back()const {
	assert(size() > 0);
	return *(_finish - 1);
}

at()

template <typename T>
T& vector<T>::at(size_t pos) {
	assert(pos < size());
	return _start[pos];
}
template <typename T>
const T& vector<T>::at(size_t pos)const {
	assert(pos < size());
	return _start[pos];
}

六、其他函数

swap()

template <typename T>
void vector<T>::swap(vector<T>& vtr) {
	::swap(_finish, vtr._finish);
	::swap(_start, vtr._start);
	::swap(_end_of_storage, vtr._end_of_storage);
}

data()

template <typename T>
T* vector<T>::data() {
	return _start;
}

template <typename T>
const T* vector<T>::data()const {
	return _start;
}

完整代码

vector.h 文件

#pragma once
#include <iostream>
#include <cstdlib>
#include <cassert>
namespace yw {
	template <class T, class Ref, class Ptr>
	struct Iterator {
		typedef Iterator<T, Ref, Ptr> self;

		//模板构造函数写法
		//Iterator(T* it) :_it(it) {};		//也可以
		Iterator<T, Ref, Ptr>(T* it) :_it(it) {};
		//self(T* it) :_it(it) {};		//error

		self& operator++() {
			_it++;
			return *this;
		}
		self operator++(int) {
			self tmp(_it++);
			return tmp;
		}
		self& operator--() {
			_it--;
			return *this;
		}
		self operator--(int) {
			self tmp(_it--);
			return tmp;
		}
		Ref operator*() {
			return *_it;
		}
		Ptr operator->() {
			return _it;
		}
		bool operator==(const self& it) {
			return _it == it._it;
		}
		bool operator!= (const self& it) {
			return _it != it._it;
		}

		T* _it;
	};
	template <class Iterator, class Ref, class Ptr>
	struct Reverse_Iterator {
		typedef Reverse_Iterator<Iterator, Ref, Ptr> self;

		Reverse_Iterator(Iterator it) :_it(it) {};

		self& operator++() {
			--_it;
			return *this;
		}
		self operator++(int) {
			self tmp(_it--);
			return tmp;
		}
		self& operator--() {
			++_it;
			return *this;
		}
		self operator--(int) {
			self tm(_it++);
			return tmp;
		}
		Ref operator*() {
			return *(_it);
		}

		Ptr operator->() {
			return _it;
		}
		bool operator==(const self& it) {
			return it._it == _it;
		}
		bool operator!=(const self& it) {
			return it._it != _it;
		}
		Iterator _it;
	};

	template <class T>
	class vector {
	public:
		typedef Iterator<T, T&, T*> iterator;
		typedef Iterator<T, const T&, const T*> const_iterator;
		typedef Reverse_Iterator<iterator, T&, T*> reverse_iterator;
		typedef Reverse_Iterator<const_iterator, const T&, const T*> const_reverse_iterator;
 
		//默认成员函数
		vector<T>();
		vector<T>(size_t n, const T& val = T());
		vector<T>(int n, const T& val = T());
		vector<T>(long n, const T& val = T());
		template <typename InputIterator>
		vector<T>(InputIterator first, InputIterator last);
		vector(const vector<T>& vtr);
		vector<T>& operator=(const vector<T>& vtr);
		~vector();

		//容量和大小相关函数
		size_t size()const;
		size_t capacity()const;
		void resize(size_t n, const T& val = T());
		void reserve(size_t n);
		bool empty()const;

		//迭代器相关函数
		iterator begin();
		iterator end();
		const_iterator begin()const;
		const_iterator end()const;
		const_iterator cbegin()const;
		const_iterator cend()const;
		reverse_iterator rbegin();
		reverse_iterator rend();
		const_reverse_iterator rbegin()const;
		const_reverse_iterator rend()const;
		const_reverse_iterator crbegin()const;
		const_reverse_iterator crend()const;

		//修改容器相关函数
		void push_back(const T& val);
		void pop_back();
		iterator erase(iterator pos);
		iterator erase(iterator first, iterator last);
		iterator insert(iterator pos, const T& val);
		iterator insert(iterator pos, size_t n, const T& val);
		template<typename InoutIterator>
		iterator insert(iterator pos, InoutIterator first, InoutIterator last);

		//访问容器相关函数
		T& operator[](size_t pos);
		const T& operator[](size_t pos)const;
		T& at(size_t pos);
		const T& at(size_t pos)const;
		T& front();
		const T& front()const;
		T& back();
		const T& back()const;

		//其他函数
		void swap(vector<T>& vtr);
		T* data();
		const T* data()const;
	private:
		T* _start;
		T* _finish;
		T* _end_of_storage;
	};
	
	//类外实现成员函数
	template <typename T>
	vector<T>::vector() 
		:_start(nullptr)
		, _finish(nullptr)
		, _end_of_storage(nullptr) 
	{}

	template <typename T>
	vector<T>::vector(size_t n, const T& val) {
		reserve(n);
		for (size_t i = 0; i < n; i++) {
			_start[i] = val;
		}
		_finish = _start + n;
	}

	template <typename T>
	vector<T>::vector(int n, const T& val) {
		reserve(n);
		for (size_t i = 0; i < n; i++) {
			_start[i] = val;
		}
		_finish = _start + n;
	}

	template <typename T>
	vector<T>::vector(long n, const T& val) {
		reserve(n);
		for (size_t i = 0; i < n; i++) {
			_start[i] = val;
		}
		_finish = _start + n;
	}

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

	/* template <typename T>
	vector<T>::vector(const vector<T>& vtr) {
		_start = new T[vtr.capacity()];
		_finish = _start + vtr.size();
		_end_of_storage = _start + vtr.capacity();
		for (size_t i = 0; i < size(); i++) {
			_start[i] = vtr[i];
		}
	} */

	template <typename T>
	vector<T>::vector(const vector<T>& vtr) {
		reserve(vtr.capacity());
		for (auto e : vtr) {
			push_back(e);
		}
	}

	/* template <typename T>
	vector<T>& vector<T>::operator=(const vector<T>& vtr) {
		if (&vtr != this) {
			delete[] _start;
			_start = new T[vtr.capacity()];
			for (size_t i = 0; i < vtr.size(); i++) {
				_start[i] = vtr[i];
			}
			_finish = _start + vtr.size();
			_end_of_storage = _start + vtr.capacity();
		}
		return *this;
	} */

	template <typename T>
	vector<T>& vector<T>::operator=(const vector<T>& vtr) {
		if (&vtr != this) {
			vector<T> tmp = vtr;
			swap(tmp);
		}
		return *this;
	}

	template <typename T>
	vector<T>::~vector() {
		if (_start != nullptr) {
			delete[] _start;
			_start = _finish = _end_of_storage = nullptr;
		}
	}

	template <typename T>
	typename vector<T>::iterator vector<T>::begin() {
		return iterator(_start);
	}

	template <typename T>
	typename vector<T>::iterator vector<T>::end() {
		return iterator(_finish);
	}

	template <typename T>
	typename vector<T>::const_iterator vector<T>::begin()const {
		return const_iterator(_start);
	}

	template <typename T>
typename vector<T>::const_iterator vector<T>::end()const {
	return const_iterator(_finish);
}

	template <typename T>
	typename vector<T>::const_iterator vector<T>::cbegin()const {
		return const_iterator(_start);
	}

	template <typename T>
	typename vector<T>::const_iterator vector<T>::cend()const {
		return const_iterator(_finish);
	}

	template <typename T>
	typename vector<T>::reverse_iterator vector<T>::rbegin() {
		return reverse_iterator(iterator(_finish - 1));
	}

	template <typename T>
	typename vector<T>::reverse_iterator vector<T>::rend() {
		return reverse_iterator(iterator(_start - 1));
	}

	template <typename T>
	typename vector<T>::const_reverse_iterator vector<T>::rbegin()const {
		return const_reverse_iterator(const_iterator(_finish - 1));
	}

	template <typename T>
	typename vector<T>::const_reverse_iterator vector<T>::rend()const {
		return const_reverse_iterator(const_iterator(_start - 1));
	}

	template <typename T>
	typename vector<T>::const_reverse_iterator vector<T>::crbegin()const {
		return const_reverse_iterator(const_iterator(_finish - 1));
	}

	template <typename T>
	typename vector<T>::const_reverse_iterator vector<T>::crend()const {
		return const_reverse_iterator(const_iterator(_start - 1));
	}

	template <typename T>
	size_t vector<T>::size()const {
		return _finish - _start;
	}

	template <typename T>
	size_t vector<T>::capacity()const {
		return _end_of_storage - _start;
	}

	template <typename T>
	void vector<T>::resize(size_t n, const T& val) {
		if (capacity() < n) {
			reserve(n);
		}
		if (size() > n)
			_finish = _start + n;
		else {
			for (size_t i = 0; i < n - size(); i++) {
				*(_finish++) = val;
			}
		}
	}
	
	template <typename T>
	void vector<T>::reserve(size_t n) {
		if (capacity() < n) {
			T* tmp = new T[n];
			size_t len = size();
			for (size_t i = 0; i < size(); i++) {
				tmp[i] = _start[i];
			}
			delete[] _start;
			_start = tmp;
			_finish = _start + len;
			_end_of_storage = _start + n;
		}
	}

	template <typename T>
	bool vector<T>::empty()const {
		return _start == _finish;
	}
	
	template <typename T>
	void vector<T>::push_back(const T& val) {
		if (size() + 1 == capacity()) {
			reserve(size() + 1);
		}
		*(_finish++) = val;
	}

	template <typename T>
	void vector<T>::pop_back() {
		assert(size() > 0);
		_finish--;
	}

	template <typename T>
	typename vector<T>::iterator vector<T>::erase(iterator pos) {
		assert(pos._it != nullptr && pos._it < _finish);
		for (T* begin = pos._it; begin != _finish; begin++) {
			*begin = *(begin + 1);
		}
		_finish--;
		return pos;
	}

	template <typename T>
	typename vector<T>::iterator vector<T>::erase(iterator first, iterator last) {
		assert(first._it >= _start && last._it <= _finish && last._it != nullptr);
		iterator ret = last;
		for (T* begin = last._it; begin != _finish; begin++) { 
			*(first++) = *(last++);
		}
		_finish -= (last._it - first._it);
		return ret;
	}

	template <typename T>
	typename vector<T>::iterator vector<T>::insert(iterator pos, size_t n, const T& val) {
		size_t len = pos._it - _start;
		size_t cap = n + size();
		if (n + size() > capacity()) {
			reserve(n + size());
		}
		for (iterator it = end() - 1; it != pos - 1; it--) {
			*(it + n) = *it;
		}
		for (size_t i = 0; i < n; i++) {
			_start[len + i] = val;
		}
		_finish = _start + cap;
		return iterator(_start + len);
	}

	template <typename T>
	template <typename InputIterator>
	typename vector<T>::iterator vector<T>::insert(iterator pos, InputIterator first, InputIterator last) {
		size_t n = last - first;
		size_t len = pos._it - _start;
		size_t cap = n + size();
		if (n + size() > capacity()) {
			reserve(n + size());
		}
		for (iterator it = end() - 1; it != pos - 1; it--) {
			*(it + n) = *it;
		}
		for (size_t i = 0; i < n; i++) {
			_start[len + i] = *(first++);
		}
		_finish = _start + cap;
		return iterator(_start + len);
	}

	template <typename T>
	T& vector<T>::operator[](size_t pos) {
		assert(pos < size());
		return _start[pos];
	}

	template <typename T>
	const T& vector<T>::operator[](size_t pos)const {
		assert(pos < size());
		return _start[pos];
	}

	template <typename T>
	T& vector<T>::front() {
		assert(size() > 0);
		return *_start;
	}

	template <typename T>
	const T& vector<T>::front()const {
		assert(size() > 0);
		return *_start;
	}

	template <typename T>
	T& vector<T>::back() {
		assert(size() > 0);
		return *(_finish - 1);
	}

	template <typename T>
	const T& vector<T>::back()const {
		assert(size() > 0);
		return *(_finish - 1);
	}

	template <typename T>
	T* vector<T>::data() {
		return _start;
	}

	template <typename T>
	const T* vector<T>::data()const {
		return _start;
	}

	template <typename T>
	T& vector<T>::at(size_t pos) {
		assert(pos < size());
		return _start[pos];
	}
	template <typename T>
	const T& vector<T>::at(size_t pos)const {
		assert(pos < size());
		return _start[pos];
	}

	template <typename T>
	void vector<T>::swap(vector<T>& vtr) {
		::swap(_finish, vtr._finish);
		::swap(_start, vtr._start);
		::swap(_end_of_storage, vtr._end_of_storage);
	}
}

test.cpp 文件(测试)

#define _CRT_SECURE_NO_WARNINGS
#include <string>
#include <algorithm>
#include <iostream>
#include "vector.h"
using namespace yw;
int main() {
	vector<int> vtr(10, 5);
	for (auto e : vtr) {
		std::cout << typeid(e).name();
		std::cout << e;
	}
	return 0;
}

❗️注意:时间有限,所以该测试并没有对 vector 每个接口进行详细的测试,只是能够编译成功运行


本篇文章到这里就结束啦,欢迎大家批评指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值