文章目录
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;
};
🌸注:
- 为了防止与标准库中的 vector 命名冲突,所以需要将我们自己实现的 vector 放到自己的命名空间中
- 所有的 vector 成员函数默认在类内定义,在类外实现
- vector 中的容器为三个指针,其分别指向容器的不同位置,如下图:
- 上图中,_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;
}
❗️注意:
-
该构造函数知道其需要用于存储 n 个数据的空间,所以最好用 reserve 函数一次性开辟好空间,避免插入元素时需要增容多次,导致效率降低
-
如果只实现上述一种情况就会发生下面的问题:
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;
}
拷贝构造函数
- 老版写法
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 元素也会失效
🌸总结:
-
如果 vector 当中存储的元素类型是内置类型(int)或浅拷贝的自定义类型(Date),使用 memcpy 函数进行进行拷贝构造是没问题的
-
但如果 vector 当中存储的元素类型是深拷贝的自定义类型(string),则使用 memcpy 函数将不能达到我们想要的效果
🌸老版写法避免深浅拷贝问题的方法:
for (size_t i = 0; i < size(); i++) {
_start[i] = vtr[i]; //这里会调用容器元素的 operator=,避免了浅拷贝问题
}
- 新版写法
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 时类似的问题
赋值运算符重载
🌸赋值运算符重载也涉及深浅拷贝的问题,这里提供两种写法:
- 传统写法
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 函数进行拷贝
- 新版写法
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;
}
}
❗️注意:
-
在进行操作之前需要提前记录当前容器当中有效数据的个数。因为我们最后需要更新 _finish 指针,而 _finish = _start + size(),当 _start 指针的指向改变后,我们再调用 size(),通过 _finish - _start 计算出的有效数据的个数就是一个随机值了
-
不能使用 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;
};
🌸但是如果我们既想要实现正向迭代器,又想要实现反向迭代器,那上面的方法就失效了,下面介绍同时实现正向和反向迭代器的方法:
-
正向迭代器和上面写法不变,将返向迭代器封装成一个类
-
将正向迭代器封装成一个类,而反向迭代器作为正向迭代器的一个适配器(推荐)
写法一
//将反向迭代器封装成一个类
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
一、正向迭代器的成员变量
-
vector 中的迭代器就是一个指针,所以如果将正向迭代器封装成类,那么其成员变量也就是一个指向 vector 容器元素的指针,其类型为 T*
-
封装正向迭代器的类由 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 {
//...
};
🌸正向迭代器的模板参数有三个:
-
class T:表明 vector 容器中元素的数据类型
-
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;
};
- 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;
-
该代码的意思是:给自己取个别名 self
-
因为在迭代器中会有 ++、-- 等操作,其返回的仍是一个迭代器(对象),所以这样可以使代码更加清晰
//不使用 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;
}
四、正向迭代器的运算符重载
- 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;
}
- operator*() 和 operator->()
Ref operator*() {
return *_it;
}
Ptr operator->() {
return _it;
}
- operator==() 和 operator!=():本质上就是成员变量 _it 的比较
bool operator==(const self& it) {
return _it == it._it;
}
bool operator!= (const self& it) {
return _it != it._it;
}
反向迭代器
-
反向迭代器就是正向迭代器的一个适配器
-
反向迭代器也是一个类,其成员变量为一个正向迭代器
-
反向迭代器通过使用正向迭代器的接口,从而实现反向迭代器的各种操作
//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...
};
其中:
- class Iterator:表明第一个参数传入的是正向迭代器
❗️注意:
-
Iterator 只是模板参数的标识符,在这里还没有实际意义
-
这里也可以写成 class T,其并无影响,只是写成 Iterator 能够更加形象的表明反向迭代器就是正向迭代器的适配器
-
并且正向迭代器(Iterator)就是反向迭代器第一个模板参数实例化时传入的参数类型
-
反向迭代器模板参数实例化是在 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...
};
-
class Ref:与正向迭代器功能相同
-
class Ptr:与正向迭代器功能相同
二、typedef 的作用
🌸与正向迭代器相同,不多赘述
typedef Reverse_Iterator<Iterator, Ref, Ptr> self;
三、反向迭代器的运算符重载
🌸反向迭代器运算符重载的思路:通过调用正向迭代器的运算符重载实现反向迭代器的运算符重载,即适配器
- 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;
}
- operator*() 和 operator->()
Ref operator*() {
return *(_it); //相当于 _it.operator*()
}
Ptr operator->() {
return _it;
}
🌸说明一下 operator->():
该函数返回的是其成员变量,即一个正向迭代器,由于该迭代器还能继续使用 “->”,所以返回的正向迭代器还会继续使用 “->” 进行运算
- 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 每个接口进行详细的测试,只是能够编译成功运行
本篇文章到这里就结束啦,欢迎大家批评指正!