当前位置: 首页 > wzjs >正文

做网站的软件淘汰史十大搜索引擎排名

做网站的软件淘汰史,十大搜索引擎排名,网站代理建设,昆山做企业网站cSTL-vector的模拟实现 vector的模拟实现基本信息构造函数析构函数返回容量(capacity)返回元素个数(size)扩容(reserve和resize)访问([])迭代器(**iterator**&#xff09…

c++STL-vector的模拟实现

  • vector的模拟实现
    • 基本信息
      • 构造函数
      • 析构函数
      • 返回容量(capacity)
      • 返回元素个数(size)
      • 扩容(reserve和resize)
      • 访问([])
      • 迭代器(**iterator**)
      • 尾插(push_back)
      • 插入(insert)
      • 删除(erase)
      • 拷贝构造
      • 交换(swap)
      • 赋值重载(operator=)
    • 参考程序

vector的模拟实现

建议先看c++STL-string的模拟实现-CSDN博客。

string的模拟实现用的是顺序表的模板。

这里的模拟实现模仿某个STL版本的vector

基本信息

库中的vector用的是定位new和内存池。这里的模拟实现不涉及内存池的概念,所有信息采用1个数组表示,用原始的堆模拟内存池。

template<class T>
class vector {
public:typedef T* iterator;//typedef会受到访问限定符影响typedef const T* const_iterator;
private:iterator _start;iterator _finish;iterator _endofstorage;
};

请添加图片描述

vector的很多函数和string类似。

模板类在类中可以不用写全类型。比如这里:

template<class T>
class vector {...vector f(vector& x){}
};

原本应该是vector<T>,但这里不推荐去掉。

构造函数

vector的拷贝构造需要用户实现,否则默认拷贝构造只会给浅拷贝。

这里选择三个构造函数接口进行模拟实现:

//无参构造函数
explicit vector (const allocator_type& alloc = allocator_type());//用n个val去初始化
vector (size_type n, const value_type& val,const allocator_type& alloc = allocator_type());//迭代器初始化
template <class InputIterator>vector (InputIterator first, InputIterator last,const allocator_type& alloc = allocator_type());

首先将全体指针初始化为nullptr,然后根据构造对象用的形参填充数据。也就是说这里给出至少2个构造函数,只给指针初始化为nullptr的,和用指定数据填充的。

其他构造函数根据vector - C++ Reference自行实现即可。

在类里面能写模板函数。构造函数用函数模板是为了能用不同类型的迭代器初始化。但如果两个的参数类型相同,可能会自动选择最匹配的

比如:

template<T>
class vector{
public:template<InputIterator>vector(InputIterator first,InputIterator second){...}vector(size_t n, T value=T()){...}
}void f(){vector<int>a(10,0);
}

我们肯定希望vector<int>a(10,0)走的是vector(size_t n, T value=T()),但编译器却为它匹配了vector(InputIterator first,InputIterator second)

所以针对这种情况,只能加一个vector(int n, const T& value=T())的函数重载。

析构函数

直接delete[] _start;即可。不用free是因为T可能是类。

返回容量(capacity)

返回_endofstorage-_start即可。

返回元素个数(size)

返回_finish-_start即可。

扩容(reserve和resize)

扩容时用new,不用realloc,原因是T可能是类,需要调用构造函数。扩容时如果初始容量为0,需要给个非0值作为初始容量。

既然不用realloc,那等于是每次扩容都是异地扩容,需要特别注意三个迭代器指向的空间,防止旧空间的迭代器和新空间的迭代器进行计算

而且原来的数据可能不为空,所以需要将原来的数据深拷贝给新开的空间。不要用memcpy拷贝数据,如果自己选的数据类型是自定义类型,会导致深层次的浅拷贝问题导致错误初始化。

即扩容时因为是异地扩容,所以需要将之前的数据拷贝到新数组,用memcpy的话只会将原数组存储的地址拷贝到新数组而不会调用构造函数,实际它们管理的还是原来的空间,当释放就空间时,新数组存储的地址就无效。

所以需要用循环来深拷贝。

除非使用计数变量,或知道数据的位置。

reserve

判断是否有扩容的必要,即请求的容量大于初始容量时才进行扩容。

  1. 对象刚创建,经过构造函数初始化列表后指针全体为nullptr。这里给1个初始空间,实际上给不给都无所谓。
  2. 对象并非刚创建。则_start非空,需要将原来的数据拷贝给现在的数据,同时容量按2倍增速扩大。

resize

resize是在reserve的基础上将数据初始化为指定内容,在初始化时允许改变_finish的值。

访问([])

返回具体下标即可。

需要加两个,一个可读可写,一个只读。

迭代器(iterator

初学时用指针实现即可。

begin()end()要给两个版本:只读(加const修饰)和可读可写。

尾插(push_back)

  • 插入前先检查是否需要扩容。扩容后尾指针赋值并自增1即可。
  • 或先实现插入(insert),调用insert间接实现即可。

string不同,因为用的是迭代器而不是size_t,指针几乎不可能是0,所以头插可以不用特别注意。

vector的形参用的迭代器,一旦发生扩容,形参表示的迭代器会失效。所以需要记录偏移量,方便调整。

迭代器实参不能用引用,因为形参可能是函数。

插入(insert)

单个元素的插入:

  • 插入前先判断插入的位置是否在两个指针之间,在的话再尝试扩容,否则越界访问。
  • 之后挪动数据,将数据插入后,尾指针自增1。

多个元素的插入:

  • 插入前先判断插入的位置是否在两个指针之间,在的话再尝试扩容,否则越界访问。
  • 之后挪动合适数量的数据,将数据插入后,调整尾指针。

但无论是哪个,都要返回迭代器,防止迭代器失效的问题。

原容器没有指定下标插入,这里为了方便使用了下标标记。

删除(erase)

//删除指定位置的迭代器表示的
iterator erase (iterator position);
iterator erase (iterator first, iterator last);

需要先检查数组中是否还有元素。

后通过挪动数据覆盖即可。每次挪动完成后将尾指针自减。

迭代器实参不能用引用,因为形参可能是函数。

而且erase同样有可能使迭代器失效。

拷贝构造

形参为引用。

当调用拷贝构造时,编译器生成一个新的临时对象,用形参的引用对象的数据赋值给新的临时对象。

因此拷贝构造函数需要进行深拷贝。

交换(swap)

因为是一个用三个指针指向空间的不同位置来实现,所以交换两个对象,交换它们的三个指针即可。

赋值重载(operator=)

//c++98自带的用vector对象进行拷贝构造
vector& operator= (const vector& x);

赋值重载的形参不用引用,使传参过程中会调用拷贝构造来生成形参的临时对象。

之后形参的临时对象和*this,两个对象交换(swap)成员指针即可,临时对象变成了*this,并以*this的面目活下去,而原*this变成了临时对象调用析构函数。

参考程序

#pragma once
#include<cassert>namespace mystd {template<class T>void swap(T& a, T& b) {T tmp = a;a = b;b = tmp;}template<class T>class vector {public:typedef T* iterator;typedef const T* const_iterator;//构造函数vector<T>():_start(nullptr), _finish(nullptr), _endofstorage(nullptr){}vector<T>(size_t n, const T& val = T()): _start(nullptr), _finish(nullptr), _endofstorage(nullptr) {reserve(n);_finish = _start + n;for (size_t i = 0; i < n; i++) {_start[i] = val;}}//析构函数~vector<T>() {delete[]_start;_start = _finish = _endofstorage = nullptr;}//获取容量信息size_t capacity() const {return _endofstorage - _start;}//获取数量size_t size() const {return _finish - _start;}//扩容void reserve(size_t n) {while (n > capacity()) {size_t sz = size();size_t new_c = capacity();new_c = new_c == 0 ? n : new_c * 2;T* tmp = new T[new_c]{ T() };if (_start != nullptr) {for (size_t i = 0; i < sz; i++) {tmp[i] = _start[i];}}_start = tmp;_finish = tmp + sz;_endofstorage = tmp + new_c;}}void resize(size_t n, const T& val) {reserve(n);for (size_t i = size(); i < n; i++)_start[i] = val;_finish = _start + n;}//访问T& operator[](size_t pos) {assert(pos < size());return _start[pos];}const T& operator[](size_t pos) const {assert(pos < size());return _start[pos];}//迭代器iterator begin() {return _start;}iterator end() {return _finish;}const_iterator begin() const {return _start;}const_iterator end() const {return _finish;}//插入//单个元素iterator insert(iterator pos, const T& val) {assert(pos >= begin());assert(pos <= end());size_t sz = pos - begin();//计算偏移量reserve(size() + 1);pos = begin() + sz;auto End = end();while (End > pos) {*End = *(End - 1);--End;}*End = val;_finish++;return pos;}//尾插void push_back(const T& val) {insert(end(), val);}//删除//删除指定迭代器iterator erase(iterator pos) {assert(pos >= begin());assert(pos < end());auto tmp = pos;while (tmp < _finish) {*tmp = *(tmp + 1);++tmp;}--_finish;return pos;}//删除区域的迭代器//左闭右开iterator erase(iterator Begin, iterator End) {assert(Begin >= begin());assert(End <= end());assert(Begin <= End);size_t sz = size_t(End - Begin);iterator tmp = Begin;while (tmp + sz < end()) {*tmp = *(tmp + sz);++tmp;}_finish = tmp;return Begin;}//尾删void pop_back() {erase(end() - 1);}//拷贝构造vector<T>(const vector<T>& a):_start(nullptr), _finish(nullptr), _endofstorage(nullptr) {reserve(capacity());for (auto& x : a)push_back(x);}//交换void swap(vector<T>& b) {vector<T>& a = *this;mystd::swap(a._start, b._start);mystd::swap(a._finish, b._finish);mystd::swap(a._endofstorage, b._endofstorage);}//赋值重载vector<T>& operator=(vector<T> tmp) {swap(tmp);return *this;}private:iterator _start;iterator _finish;iterator _endofstorage;};
}
http://www.dtcms.com/wzjs/354531.html

相关文章:

  • 网站建设细节企业网站seo排名
  • 旅游网站制作视频百度云360建站系统
  • 网站建设免费软件有哪些百度软件优化排名
  • 一个产品有两个品牌怎么做网站网站注册时间查询
  • html做网站公告西安seo关键词推广
  • 3d效果图什么网站做的好我的百度购物订单
  • 简单个人网站开发seo研究协会网是干什么的
  • 网站建设的规划书抖音搜索seo软件
  • 古建设计素材网站外国搜索引擎登录入口
  • 开发php网站建设百度商家版下载
  • 用table做的网站南宁百度seo优化
  • 深圳给企业做网站营销方式和手段
  • 襄阳做网站多少钱chatgpt 网站
  • 太原建站模板搭建天津关键词优化专家
  • 民权做网站网络推广是什么
  • 手机网站的制作湖南网站seo公司
  • 福州网站建设热线电话重庆seo网站管理
  • 成功的营销网站的例子汕头seo优化培训
  • 网站设计的流程是怎样的google浏览器官网下载
  • 响应式网站建设平台建站网站关键词优化
  • 做任务赚钱的网站 知乎有没有免费的写文案的软件
  • 中山网站建设解决方案百度推广公司怎么代理到的
  • 备案域名是什么意思怎么优化网络
  • 在哪个网站上做简历债务优化是什么意思
  • 手机建设网站策划书百度怎么打广告在首页
  • 手机网站建设制作教程app营销策略有哪些
  • wordpress移机关键字排名优化公司
  • seo优化查询西安seo站内优化
  • 单位网站建设实施方案市场调研方案怎么写
  • 券妈妈网站是如何做的宁德seo