C++ -- vector类模拟实现
创始人
2024-06-02 11:41:23
0

文章目录

  • C++ -- vector类模拟实现
    • 0. 成员变量
    • 1. 构造函数
    • 2. 析构函数
    • 3. reserve方法
    • 5. resize方法
    • 6. insert方法
    • 7. erase方法
    • 8. push_back方法
    • 9. pop_back方法
    • 10. []运算符重载
    • 11. 拷贝构造
    • 12. 迭代器
    • 13. 完整代码

C++ – vector类模拟实现

0. 成员变量

template
typedef T* iterator;
typedef const T* const_iterator;
iterator _start;
iterator _finish;
iterator _end_of_storage;
  1. 为什么这里需要模板呢?

因为我们使用数组可能是int、char等等类型,这里就依靠是顺序存储的特性,就直接用指针来充当成员变量。

1. 构造函数

vector():_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{}vector(size_t n, const T& val = T()) //T()->T类型的构造 && const T&引用修饰->起别名延长了生命周期:_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{reserve(n);for (size_t i = 0; i < n; ++i){push_back(val);}
}template 
vector(InputIterator first, InputIterator last) //迭代器区间:_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{while (first != last){push_back(*first);++first;}
}
  1. 为什么这里的const T& val = T()?

这里的写法是为了给一个默认值,T()是针对自定义类型:string、vector等等。内置类型int()、char()等都是由编译器来初始化

2. 析构函数

~vector()
{delete[] _start;_start = _finish = _end_of_storage = nullptr;
}

3. reserve方法

void reserve(size_t capa)
{if (capa > capacity()){size_t len = size(); //OK:记录当前长度T* tmp = new T[capa];if (_start != nullptr){for (size_t i = 0; i < len; ++i){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + len;_end_of_storage = _start + capa;}
}
  1. 操作:

    • 是否扩容
    • 拷贝数据
    • 变化成员变量
  2. 为什么_finish = _start + len,而不是 _finish = _start + size()?

因为size() = _finish - _start , _finish = _start + size() --> _finish = _start + _finiosh - _start

5. resize方法

void resize(size_t capa, T val = T())
{if (capa < size()){_finish = _start + capa;}else{if (capa > capacity()){reserve(capa);}while (_finish != _start + capa){*_finish = val;++_finish;}}
}

6. insert方法

iterator insert(iterator pos, const T& val)
{assert(pos >= _start && pos <= _finish);if (_finish == _end_of_storage){size_t len = pos - _start; //记录当前pos距离_start的距离reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + len; //扩容:因为new的新空间会导致pos不在空间中导致后面while循环出错(pos失效解决方案)}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = val;++_finish;return pos;
}
  1. 为什么需要接受pos呢?

扩容问题会导致new出新的空间给_start,连续插入会导致pos迭代器失效

  1. 对没有改动pos进行测试:
void test1()
{int arr[] = { 1,2,3,4};vector v(arr, arr + sizeof(arr) / sizeof(int));v.insert(v.end(), 10);for (auto i : v){cout << i << " ";}cout << endl;
}

reserve后pos不在[_start, _finish)范围内,解决方案就是改动pos

7. erase方法

iterator erase(iterator pos)
{assert(pos >= _start && pos < _finish);iterator start = pos + 1;while (start != _finish){*(start - 1) = *start;++start;}--_finish;return pos; //没有返回pos就导致迭代器失效
}

visual studio2019中的erase机制是一定是会pos迭代器失效。

8. push_back方法

void push_back(const T& val)
{if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*(_finish) = val;++_finish;
}

9. pop_back方法

void pop_back()
{assert(!empty());--_finish;
}

10. []运算符重载

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

11. 拷贝构造

vector(const vector& v):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{reserve(v.capacity());_start = new T[v.capacity()];for (size_t i = 0; i < v.size(); ++i){_start[i] = v._start[i];}_finish = _start + v.size();_end_of_storage = _start + v.capacity();
}
  1. 为什么用for循环依次拷贝数据,而不是memcpy()呢?

假如是string类型,拷贝的时候就需要深拷贝,但是memcpy是浅拷贝

12. 迭代器

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

13. 完整代码

#pragma once
#include namespace myvector
{templateclass vector{public:typedef T* iterator;typedef const T* const_iterator;vector():_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){}vector(size_t n, const T& val = T()) //T()->T类型的构造 && const T&引用修饰->起别名延长了生命周期:_start(nullptr),_finish(nullptr),_end_of_storage(nullptr){reserve(n);for (size_t i = 0; i < n; ++i){push_back(val);}}vector(int n, const T& val = T()) //T()->T类型的构造 && const T&引用修饰->起别名延长了生命周期:_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){reserve(n);for (int i = 0; i < n; ++i){push_back(val);}}template vector(InputIterator first, InputIterator last):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){while (first != last){push_back(*first);++first;}}/*vector(const vector& v):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){reserve(v.capacity());for (auto i : v){push_back(i);}}*///vector<自定义类型>-->两次析构会程序崩溃//vector(const vector& v)//	:_start(nullptr)//	, _finish(nullptr)//	, _end_of_storage(nullptr)//{//	reserve(v.capacity());//	_start = new T[v.capacity()];//	memcpy(_start, v._start, sizeof(T) * v.size()); //memcpy也是浅拷贝//	_finish = _start + v.size();//	_end_of_storage = _start + v.capacity();//}vector(const vector& v):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){reserve(v.capacity());_start = new T[v.capacity()];for (size_t i = 0; i < v.size(); ++i){_start[i] = v._start[i];}_finish = _start + v.size();_end_of_storage = _start + v.capacity();}iterator begin(){return _start; //传值返回:临时对象具有常性}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}T& operator[](const size_t& pos){assert(pos < size());return _start[pos];}const T& operator[](const size_t& pos) const{assert(pos < size());return _start[pos];}size_t capacity() const{return _end_of_storage - _start;}size_t size() const{return _finish - _start;}void resize(size_t capa, T val = T()){if (capa < size()){_finish = _start + capa;}else{if (capa > capacity()){reserve(capa);}while (_finish != _start + capa){*_finish = val;++_finish;}}}//void reserve(size_t capa)//{//	if (capa > capacity())//	{//		size_t len = size(); //OK:记录当前长度//		T* tmp = new T[capa];//		if (_start != nullptr)//		{//			memcpy(tmp, _start, sizeof(T) * size()); //memcpy是浅拷贝//			delete[] _start;//		}//		_start = tmp;//		_finish = _start + len;//		//_finish = _start + size(); //err:size() = _finish - _start --> _finish = _finish//		_end_of_storage = _start + capa;//	}//}void reserve(size_t capa){if (capa > capacity()){size_t len = size(); //OK:记录当前长度T* tmp = new T[capa];if (_start != nullptr){for (size_t i = 0; i < len; ++i){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + len;//_finish = _start + size(); //err:size() = _finish - _start --> _finish = _finish_end_of_storage = _start + capa;}}void push_back(const T& val){if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*(_finish) = val;++_finish;}bool empty(){return _start == _finish;}void pop_back(){assert(!empty());--_finish;}iterator insert(iterator pos, const T& val){assert(pos >= _start && pos <= _finish);if (_finish == _end_of_storage){size_t len = pos - _start; //记录当前pos距离_start的距离reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + len; //扩容:因为new的新空间会导致pos不在空间中导致后面while循环出错(pos失效解决方案)}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = val;++_finish;return pos;}iterator erase(iterator pos){assert(pos >= _start && pos < _finish);iterator start = pos + 1;while (start != _finish){*(start - 1) = *start;++start;}--_finish;return pos; //没有返回pos就导致迭代器失效}~vector(){delete[] _start;_start = _finish = _end_of_storage = nullptr;}void out(const vector& v){for (size_t i = 0; i < v.size(); ++i){cout << v[i] << " ";}cout << endl;vector::const_iterator it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;}private:iterator _start;iterator _finish;iterator _end_of_storage;};
}

相关内容

热门资讯

英雄联盟之传奇归来大结局谁赢了 英雄联盟之传奇归来大结局谁赢了英雄联盟之宴冲传奇归来大结局中,蓝队最终获得了胜利。赢得胜利需要团队间...
老农民电视剧一共多少集? 老农民电视剧一共多少集?60年变迁,60集苦难。由陈宝国主演的《老农民》一共有60集。
求道士下山,声音最后能听见的 求道士下山,声音最后能听见的只有枪版要么不知道能不能听到
项目管理作业word,项目管理...   # XI。项目冲突的原因。      1.多个上级领导;      2.高压环境;      3...
第一个字是天的成语和最后一个字... 第一个字是天的成语和最后一个字是天的成语有哪些,地Fox is behind him and wan...
互联网创业大赛计划书,互联网创...   36Kr得知SD-      而广域网运维解决方案服务商“云起网”也于近日完成了A轮融资。本轮融...
正安安场海龙驾校报名处,正安创...   昨晚(10号)      遵义遭遇了一场      大雨、闪电、强风      生活在君的朋友圈...
学校餐饮创业项目加盟,重庆大学...   还在为找工作发愁吗?      还在担心创业难吗?      六月城里的大学生      就业活...
挣钱创业商机,农民工返乡创业现...       qvj2l q49k 0/7500 c 0222 e 044 ee 4 BD ...
自学比较容易考的证书,女生适合...   合肥怎么报房产证考多少钱?申请流程包括申请专业家居督察证书需要多少费用。任何一个从事任何行业的人...