当前位置:网站首页>vector的模拟实现
vector的模拟实现
2022-06-22 14:34:00 【股神。】
vector的成员变量
- _start:指向元素开始的位置
- _finish:指向最后一个元素的下一个位置
- _endofstorage:指向从堆区开辟的空间的末尾的下一位置

template<class T>
class vector
{
public:
//迭代器
typedef T* iterator;
typedef const T* const_iterator;
//反向迭代器迭代器
typedef reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
typedef reverse_iterator<iterator, T&, T*> reverse_iterator;
//、、、、、、
//各种成员函数
//、、、、、、
private:
iterator _start;
iterator _finish;
iterator _endofstorage;
};
构造函数
1、无参构造
vector()
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{
}
2、采用迭代器的构造方法
template<class InputerIterator>//新建一个模板参数是为了可以传多种迭代器,而不是只能传vector的迭代器
vector(InputerIterator first, InputerIterator last)//vector有一种构造方法是vector v(v1.begin(),v1.end())
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{
while (first != last)
{
push_back(*first);
++first;
}
}
3、拷贝构造
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endofstorage, v._endofstorage);
}
vector(const vector<T>& v)//拷贝构造必需传引用,如果不传引用,就是传值,传值又是一次拷贝构造,进而死循环,所以不能像operator=那样写。
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{
vector<T> tmp(v.begin(), v.end());
swap(tmp);
}
赋值运算符重载
vector<T>& operator=(vector<T> v)
{
swap(v);
return *this;
}
析构函数
~vector()
{
if (_start)
{
delete[] _start;//销毁所开辟的所有空间
_start = _finish = _endofstorage = nullptr;
}
}
reverse()扩容
size_t size() const
{
return _finish - _start;//指针-指针,因为同类型得到的是这段空间的元素的个数。
}
void reserve(size_t n)
{
if (n > capacity())
{
size_t sz = size();
T* tmp = new T[n];
if (_start)//_start不为空,说明原来有数据,要拷贝
{
//memcpy是浅拷贝,当T是string时,字符串是存在堆中的,string只存了指向这个字符串的指针、size、capacity。
//因此使用memcpy也只是把指针的地址重新赋值给了tmp,当delete[] _start;就已经销毁了字符串的空间。
//然后tmp又赋值给了_start,程序结束,调用析构函数,又要再次销毁字符串的空间,同一块空间被释放了2次,程序错误
//因此不能使用memcpy
//memcpy(tmp, _start, sizeof(T) * size());//大部分情况是对的,但是涉及深拷贝问题会有错误
for (size_t i = 0; i < sz; i++)
{
//相当于string =string 调用了string类中的operator=,operator是深拷贝。
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
// _finish = _start + size();这句代码有误,因为_start的位置改了,所计算的size也是错的,应该提前保存原来数组的大小,即sz
_finish = _start + sz;
_endofstorage = _start + n;
}
}
push_back
当_finish == _endofstorage说明空间不够需要扩容。
void push_back(const T& x)
{
if (_finish == _endofstorage)
{
reserve(capacity() == 0 ? 4 : (capacity() * 2));
}
*_finish = x;
++_finish;
}
resize()
void resize(size_t n, const T& val = T())//const &会延长匿名对象的生命周期,延长到整个作用域,而不是仅是这一行代码
{
if (n < size())//如果定义的空间比原来还要小,即让finish指向_start+n的位置,而不用销毁空间
{
_finish = _start+n;
}
else
{
if (n > capacity())//定义的n大于容量了,扩容
{
reserve(n);
}
while (_finish != _start + n)//赋值
{
*_finish = val;
_finish++;
}
}
}
insert
iterator insert(iterator pos, const T& x)//传迭代器是规定,看文档;返回值要返回新插入元素位置的迭代器,也是为了处理迭代器失效问题
{
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endofstorage)
{
// 扩容会导致pos失效,扩容需要更新一下pos,因为扩容可能是异地扩容
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : (capacity() * 2));
pos = _start + len;
}
iterator end = _finish - 1;
//这个while循环是将数据往后挪一个位置
while (end >= pos)
{
*(end + 1) = *end;
--end;
}
*pos = x;
_finish++;
return pos;
}
erase
iterator erase(iterator pos)
{
assert(pos >= _start);
assert(pos < _finish);//这里不能用=,因为可能要删除最后一个元素
iterator begin = pos + 1;//让pos后一个元素 覆盖 pos位置上的元素
while (begin < _finish)
{
*(begin - 1) = *begin;
begin++;
}
--_finish;
return pos;
}
剩余的简单成员函数
void pop_back()//尾删
{
assert(_finish > _start);
--_finish;
}
const T& operator[](size_t i)const
{
assert(i < size());
return _start[i];
}
T& operator[](size_t i)
{
assert(i < size());
return _start[i];
}
size_t capacity() const//返回容量大小
{
return _endofstorage- _start;
}
正向迭代器
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
反向迭代器
方向迭代器的rbegin在正向迭代的end上,反向迭代器rend在正向迭代器的begin上。
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
我们为反向迭代器新建了一个类
namespace Lgc
{
//反向迭代器的end就是正向迭代器的begin,反向迭代器的begin就是正向迭代的end,这样写是为了复用正向迭代器
//因为用的是模板,这个反向迭代器同时也可以给其他容器使用。(如vector)
template<class Iterator,class Ref,class Ptr>
class reverse_iterator
{
typedef reverse_iterator<Iterator, Ref, Ptr> self;
public:
reverse_iterator(Iterator it)
:_it(it)
{
}
Ref operator*()
{
Iterator prev = _it;//prev不能是self类型,因为如果是self则prev是个反向迭代器,--还是一个反向迭代器,在*就是调用自己的operator*,然后一直调用自己的operator*,直到栈溢出(3.15 2:41:45) 我们的本意是去调用正向迭代器的operator*
return *(--prev);//因为rbegin在正向迭代器的end上,而end的位置在_finish的位置上,要获取元素,所以要--
}
Ptr operator->()
{
return &(operator*());
}
self& operator++()
{
--_it;
return *this;
}
self operator++(int)
{
self tmp(*this);
--_it;
return tmp;
}
self& operator--()
{
++_it;//因为是反向迭代的原因,--在逻辑是就是++
return *this;
}
bool operator!= (const self& rit) const
{
return _it != rit._it;//这个不等于是调用了正向迭代器的运算符重载!=
}
private:
Iterator _it;
};
}
边栏推荐
- SDVO:LDSO+语义,直接法语义SLAM(RAL 2022)
- Countdown to the conference - Amazon cloud technology innovation conference invites you to build a new AI engine!
- 2020年蓝桥杯省赛真题-走方格(DP/DFS)
- Database connection pool: implementation of connection pool function point
- How MySQL modifies a field to not null
- 蓝桥杯2019年国赛最长子序列
- Hello, big guys. Error reporting when using MySQL CDC for the first time
- Please, don't be brainwashed. This is the living reality of 90% of Chinese people
- 迷宫问题(BFS记录路径)
- 专业“搬砖”老司机总结的 12 条 SQL 优化方案,非常实用!
猜你喜欢

Verilog使用inout信号的方法

I rely on the sideline to buy a house in full one year: the industry you despise will make a lot of money in the next ten years!

The IPO of Tian'an technology was terminated: Fosun and Jiuding were shareholders who planned to raise 350million yuan

Community article | mosn building subset optimization ideas sharing

晒晒我这两年的私活单,业余时间月入6k,有份副业也太香啦

二分查找(整数二分)

On the routing tree of gin

NF RESNET: network signal analysis worth reading after removing BN normalization | ICLR 2021

Using virtual serial port to debug serial port in keil MDK

Development status of full color LED display
随机推荐
Recommend several AI Intelligent Platforms
"Software defines the world, open source builds the future" 2022 open atom global open source summit will open at the end of July
数字人民币可以买理财产品了!建行APP在试点地区上线服务专区,实测体验如何?
What does password security mean? What are the password security standard clauses in the ISO 2.0 policy?
Application of mongodb in Tencent retail premium code
基础版现在SQL分析查询不能用了吗?
Method of using inout signal in Verilog
又可以这样搞nlp(分类)
Wallys/DR7915-wifi6-MT7915-MT7975-2T2R-support-OpenWRT-802.11AX-supporting-MiniPCIe
向量6(继承)
晒晒我这两年的私活单,业余时间月入6k,有份副业也太香啦
OOP 多重收纳(类模板)
FreeRTOS task priority and interrupt priority
向量2(友元及拷贝构造)
Ml notes matrix fundamental, gradient descent
ML笔记-matrix fundamental, Gradient Descent
Countdown to the conference - Amazon cloud technology innovation conference invites you to build a new AI engine!
What happened to those who didn't go to college
“软件定义世界,开源共筑未来” 2022开放原子全球开源峰会7月底即将开启
高精度计算