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

相关内容

热门资讯

你的晚安是我的早安是什么歌曲 你的晚安是我的早安是什么歌曲苏天伦《你的早安是我的晚安》“你的晚安是我的早安”是单小源的歌曲《东京遇...
积极进取的小故事 积极进取的小故事现代的普通人,不要名人的。不能与别人重复,尽快回答   啄木鸟的故事       啄...
熊出没之探险日记3什么时候播出... 熊出没之探险日记3什么时候播出?熊出没之探险日记3,春节前播放。熊出没只是探险日记三2020年5月4...
谁知道所有有关“七”的歌?拜托... 谁知道所有有关“七”的歌?拜托了各位 谢谢就是歌曲名里有“七”这个字的!谢谢七月七迅谈日晴 看我七十...
求一本小说 女主穿越了三次 每... 求一本小说 女主穿越了三次 每次都在福临身边 后来怀孕了孩子被打掉了那个 女主叫什么雯?那个女主就是...
如果记忆不说话,流年也会开出花... 如果记忆不说话,流年也会开出花的基本信息书 名:《如果记忆不弯饥好说话,流年也会开出花》埋铅 作 者...
你好,旧时光漫画版在哪里可以看... 你好,旧时光漫画版在哪里可以看?暂时在绘心上连载
一首英文歌,男的组合唱的,MV... 一首英文歌,男的组合唱的,MV是一个婚礼的过程。求歌名。是不是darin的can'tstoplove...
为什么很多人喜欢用胶片相机? 为什么很多人喜欢用胶片相机?有一种情怀叫做“怀旧“吧,现在数码相机越来越普遍了,已经到了”全民摄影“...
女主先爱上男主,男主却不喜欢女... 女主先爱上男主,男主却不喜欢女主或者是另有所爱,最后女主男主还是在一起的穿越小说。有木有再生缘:我的...
爱情失恋伤感句子 爱情失恋伤感句子越是美好的从前,越幸福的曾经,现在只能带来锥心的疼痛,痛到撕心裂肺,肝肠寸断,终于痛...
24岁穿这个会不会显老 24岁穿这个会不会显老有点显老,这个颜色款式,颜色有点暗,没有活力,属于那种气质佳,长得高雅的女人,...
哈尔的移动城堡英语版 哈尔的移动城堡英语版可以发给我吗度盘~请查收~
秦时明月之万里长城什么时候播 秦时明月之万里长城什么时候播据说是今年暑假开播别急,官网什么的信他你就输了,12年之前底应该会出,杭...
孩子会得抽动症吗? 孩子会得抽动症吗?我天生的气性比较大,有时跟别人斗嘴时候就会手脚哆嗦,麻木,我问一下这是不是抽动症就...
亨德尔一生为音乐献出了怎样的贡... 亨德尔一生为音乐献出了怎样的贡献?亨德尔一生写了歌剧41部,清唱剧21部,以及大量的管乐器与弦乐器的...
礼仪起源和发展的经典故事? 礼仪起源和发展的经典故事?一、礼仪的起源;1、天神生礼仪;2、礼为天地人的统一体;3、礼产生于人的自...
描写桂林山水的句子有哪些? 描写桂林山水的句子有哪些?天下风光数桂林有杨万里的“梅花五岭八桂林,青罗带绕碧玉簪”;有邹应龙的“无...
避免与强敌正面对决的成语 避免与强敌正面对决的成语避免与强敌正面对决的成语避实就虚 【近义】避重就轻、避难就易、声东击西【反义...
多愁善感类的成语 多愁善感类的成语心细如发【解释】:极言小心谨慎,考虑周密。亦作“心细于发”。【出自】:吴梅《题天香石...