当前位置:网站首页>vector的底层模拟实现
vector的底层模拟实现
2022-07-02 15:07:00 【念旧~】
文章目录
vector的成员变量
什么是vector呢? vector是可变数组大小的序列容器。(跟模拟实现顺序表差不多)
模拟实现顺序表的成员变量:指针,size,capacity。
迭代器的模拟实现
iterator begin()
{
return _start;
}
iterator end()
{
reutrn _finish;
}
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
reutrn _finish;
}
获取size,capacity,判空操作
不修改数据的时候,我们建议都加上const
size_t size() const
{
return _finish - _start;
}
size_t capacity() const
{
return _endofstorage - _start;
}
bool empty() const
{
return _start == _finish;
}
reserve和resize的模拟实现(重点)
reserve针对capacity,当要调整的空间大于capacity时才会调整,小于capacity不做处理(但是不一定会调整到指定大小,
因为无论是C++编译器还是Linux编译器都有自己的增容方式)
resize针对于size ,如果要调整的个数小于size,直接砍掉。 但是调整的个数大于size,扩容后填数据
void reserve(size_t n)
{
if (n > capacity())
{
size_t sz = size();
T* tmp = new T[n];
//memcpy(tmp,_start,sizeof(T)*size()) 如果用memcpy会出现一些错误
//这个放到最后面再说
if (_start)
{
for (size_t i = 0; i < sz; i++)
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = _start + sz; //这里的_finis , _endofstorage都要重新刷新一下
_endofstorage = _start + n;
}
}
void resize(size_t n, const T& val = T())
{
if (n < size())
{
_finish = _start + n;
}
else
{
if (n > capacity())
{
reserve(n);
}
while (size() < n)
{
*_finish++ = val;
}
}
}
pop_back (尾删)和 push_back(尾插)
void push_back(const T& val)
{
if (_finish == _endofstorage) //这里是判断是否满了,不要用_start去比较了
{
size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
reserve(newcapacity);
}
*_finish = val;
_finish++;
}
void pop_back()
{
if (empty())
{
cout << "no data to delete" << endl;
return;
}
else
{
_finish--;
}
}
insert(任意位置的插入) 和 erase (任意位置的删除)
iterator insert(iterator pos, const T& val)
{
if (_finish == _endofstorage)
{
size_t len = pos - _start;
size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
reserve(newcapacity);
//这里如果发生了扩容,pos就要刷新一下
//否则就失效了
pos = _start + len;
}
iterator it = _finish - 1;
while (it >= pos)
{
*(it + 1) = *it;
--it;
}
*pos = val;
_finish++;
return pos;
}
void insert(iterator pos,size_t n ,const T& val)
{
size_t max = n + size();
if ( max > capacity())
{
size_t len = pos - _start;
reserve(max);
//这里如果发生了扩容,pos就要刷新一下
//否则就失效了
pos = _start + len;
}
size_t len = n;
iterator it = _finish - 1;
while (it >= pos)
{
*(it + len) = *it;
it--;
}
while (n)
{
n--;
*pos = val;
pos++;
}
_finish = _finish + len;
}
iterator erase(iterator pos)
{
if (empty())
{
cout << " no data to delete" << endl;
}
iterator it = pos ;
while (it < _finish-1)
{
*it = *(it + 1);
it++;
}
_finish--;
return pos;
}
构造,析构,拷贝构造,赋值重载
vector()
:_start(nullptr)
, _finish(nullptr)
,_endofstorage(nullptr)
{
}
vector(size_t n, const T& val = T())
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
_start = new T[n];
for (size_t i = 0; i < n; i++)
{
_start[i] = val;
}
_finish = _start + n;
_endofstorage = _start + n;
}
// v1(v2)
vector(const vector<T>& v)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
_start = new T[v.capacity()];
for (size_t i = 0; i < v.size(); i++)
{
_start[i] = v._start[i];
}
_finish = _start + v.size();
_endofstorage = _start + v.capacity();
}
//v1 = v2
vector<T>& operator=(vector<T> v)
{
swap(v);
return *this;
}
//类模板里面的模板函数
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
int len = last - first;
_start =_finish = new T[len];
while (first != last)
{
*_finish++ = *first++;
}
_endofstorage = _start + len;
}
void swap(vector<T>& v)
{
::swap(_start, v._start);
::swap(_finish, v._finish);
::swap(_endofstorage, v._endofstorage);
}
关于当扩容的时候用memcpy会引发的一些问题



总结:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是
浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。
边栏推荐
- Introduce the scrollintoview() method attribute in detail
- 博客主题 “Text“ 夏日清新特别版
- 2322. Remove the minimum fraction of edges from the tree (XOR and & Simulation)
- chmod命令原理及用法详解[通俗易懂]
- 几行代码搞定RPC服务注册和发现
- 绿竹生物冲刺港股:年期内亏损超5亿 泰格医药与北京亦庄是股东
- Error when uploading code to remote warehouse: remote origin already exists
- helm kubernetes包管理工具
- ROS knowledge point - message_filters
- si446使用记录(一):基本资料获取
猜你喜欢

A case study of college entrance examination prediction based on multivariate time series

QStyle实现自绘界面项目实战(二)

线性规划例题 投资的收益与风险

Tech talk activity preview | building intelligent visual products based on Amazon kVs

Smart trash can (V) - light up OLED

GeoServer:发布PostGIS数据源

简单线性规划问题

AP and F107 data sources and processing

Eye of depth (II) -- matrix and its basic operations

The poor family once again gave birth to a noble son: Jiangxi poor county got the provincial number one, what did you do right?
随机推荐
[leetcode] 14. Préfixe public le plus long
Sword finger offer 25 Merge two sorted linked lists
Sword finger offer 27 Image of binary tree
ssb门限_SSB调制「建议收藏」
超卓航科上市:募资9亿市值超60亿 成襄阳首家科创板企业
si446使用记录(二):使用WDS3生成头文件
Uniapp H5 page calls wechat payment
traceroute命令讲解
Explanation of traceroute command
博客主题 “Text“ 夏日清新特别版
Chmod command principle and usage details [easy to understand]
详细介绍scrollIntoView()方法属性
LeetCode:1380. Lucky number in matrix -- simple
uniapp H5页面调用微信支付
一年顶十年
IDEA2021.1 安装教程
畅玩集团冲刺港股:年营收2.89亿 刘辉有53.46%投票权
Vscode knowledge points - Common Errors
QStyle实现自绘界面项目实战(二)
选择 SAP Spartacus 作为 SAP Commerce Cloud Storefront 实现框架的五个理由