销售公司怎么做网站,删除wordpress,wordpress 样式引用,邢台吧李彦明目录 vector模拟实现一. vector的基本框架二. 常用方法及实现1.初始化和清理a. 默认构造函数b. 析构函数 2. 迭代器a. beginb. end 3.数据访问a. sizeb. capacityc. operator[]d. frontc. back 4.增删查改操作a. reserveb. resizec. insertd. push_backe. erasef. pop_back 5.构… 目录 vector模拟实现一. vector的基本框架二. 常用方法及实现1.初始化和清理a. 默认构造函数b. 析构函数 2. 迭代器a. beginb. end 3.数据访问a. sizeb. capacityc. operator[]d. frontc. back 4.增删查改操作a. reserveb. resizec. insertd. push_backe. erasef. pop_back 5.构造函数a.迭代器区间构造b. swapc. 拷贝构造d. operatorc.n个val的构造 三.小结1.代码结构2.迭代器失效a.插入时b.删除时 3.迭代器操作 vector模拟实现
一. vector的基本框架
templatetypename T
class vector
{
public:typedef T* iterator;private:iterator _start;iterator _finish;iterator _end_of_storage;
}使用库中的string类需要包含头文件#inlcudevector并且使用std::命名空间 _start指向起始元素的地址 _finish指向最后一个元素的下一个地址 _end_of_storage指向所申请空间结尾的下一个位置地址 其底层是将数据顺序存储的即使用一段连续的空间。
二. 常用方法及实现
以实现的顺序来依次进行介绍
1.初始化和清理
a. 默认构造函数
vector():_start(nullptr),_finish(nullptr),_end_of_storage(nullptr)
{}b. 析构函数
~vector()
{delete[] _start;_start _finish _end_of_storage nullptr;
}2. 迭代器 vector是顺序存储的结构因此可以用T*(原生指针)当做其迭代器 typedef T* iterator;
typedef const T* const_iterator;a. begin
iterator begin()
{return _start;
}
const_iterator begin() const
{return _start;
}b. end
iterator end()
{return _finish;
}
const_iterator end() const
{return _finish;
}3.数据访问
a. size
size_t size() const
{return _finish - _start;
}b. capacity
size_t capacity() const
{return _end_of_storage - _start;
}指针相减得到的是其中该类型元素的个数 c. operator[]
const T operator[](size_t pos) const
{assert(pos size());return *(_start pos);
}
T operator[](size_t pos)
{assert(pos size());return *(_start pos);
}d. front
T front()
{assert(size() 0);return *_start;
}
const T front() const
{assert(size() 0);return *_start;
}c. back
const T back() const
{assert(size() 0);return *(_finish - 1);
}4.增删查改操作
a. reserve
void reserve(size_t n)
{if (n capacity()){T* temp new T[n];//将原空间的数据拷贝到新空间中size_t sz size();for (size_t i 0; i sz; i){temp[i] *(_start i);}delete[] _start;_start temp;_finish _start sz;_end_of_storage _start n;}
}申请n个元素的空间如果n原有空间则不做操作 b. resize
void resize(size_t n, const T val T())
{if (n size()){//保留前n个元素_finish _start n;}else{//申请n个元素空间reserve(n);//新增的元素赋valiterator cur _finish;_finish _start n; while (cur ! _finish){*cur val;cur;} }
}调整元素个数为n个如果nsize只保留前n个元素如果nsize新增的元素为val。 其中如果没有传val参数则使用缺省值T()T类型的匿名对象内置类型如int() 0) c. insert
iterator insert(iterator pos, const T val)
{assert(pos _start);assert(pos _finish);//如果空间满了就扩容if (_finish _end_of_storage){//扩容后,可能使用新的空间pos指向改变size_t s pos - _start;reserve(capacity() 0 ? 4 : 2 * capacity());pos _start s;}//将pos位到最后元素都向后移动1位iterator cur _finish - 1;while (cur pos){*(cur1) *cur;--cur;}*pos val;_finish;return pos;
}扩容操作可能使用新空间所以要更新迭代器 d. push_back
void push_back(const T val)
{insert(_finish, val);
}尾插在最后一个元素的下一个位置(_finish)存放val e. erase
iterator erase(iterator pos)
{assert(pos _start);assert(pos _finish);//将pos后的元素都向前移动1位iterator cur pos 1;while (cur _finish){*(cur - 1) *cur;cur;}--_finish;return pos;
}删除pos指向的元素并返回删除位置的下一个位置的迭代器 f. pop_back
void pop_back()
{erase(_finish - 1);
}删除最后一个元素 5.构造函数
a.迭代器区间构造
templateclass InputIterator
vector(InputIterator first, InputIterator last):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{while (first ! last){push_back(*first);first;}
}通过传入的迭代器区间来根据其区间的值来创建vector对象 b. swap
void swap(vectorT v)
{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);
}交换两个同类型vector对象的内容通过作用域限定符::来调用库函数中的swap函数完成对内置类型的成员变量的交换。 c. 拷贝构造
传统写法
vector(const vectorT v):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{//提前申请空减少扩容reserve(v.size());for (const auto e : v){push_back(e);}
}现代写法 通过一个局部对象和swap来完成 vector(const vectorT v):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{//调用迭代器区间来构造temp对象vectorT temp(v.cbegin(),v.cend());swap(temp);
}通过初始化列表对成员变量进行初始化然后和经迭代器区间构造函数得到的temp对象进行交换内容完成拷贝构造。该函数调用结束局部对象temp会自动调用析构函数并销毁。 d. operator
//赋值运算符重载非构造函数
vectorT operator (vectorT v)
{swap(v);return *this;
}传参时会调用拷贝构造函数完成对局部对象v的初始化然后交换*this和v的内容完成对自身对象的赋值。 c.n个val的构造
vector(size_t n, const T val T()):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{reserve(n);for (size_t i 0; i n; i){push_back(val);}
}/*定义时n应该是非负数的所以使用size_t,但传参时通常传入的数字是int类型的
例如vectorint v(5,0);(构造含5个0的v对象)此时参数类型是(int,int)
无法做到和上面(size,int)的精准匹配编译器会选择根据
//templateclass InputIterator
//vector(InputIterator first, InputIterator last)
生成调用(int,int)的区间构造构造函数从而发生错误
所以加入下面的函数
*/
vector(int n, const T val T()):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{reserve(n);for (int i 0; i n; i){push_back(val);}
}构造的vector对象含n个val元素。其中如果没有传val参数则使用缺省值T()T类型的匿名对象内置类型如int() 0) 三.小结
1.代码结构 vector代码代码可以放在自己的命名空间中避免冲突 #include iostream
#include assert.hnamespace yyjs
{ templatetypename Tclass vector{public:typedef T* iterator;typedef const T* const_iterator;...};}上述的成员函数都是放在class vector类体中并public修饰 2.迭代器失效
a.插入时 扩容操作可能使用新空间所以要更新迭代器如果只是进行扩容迭代器pos所指向的可能就是野指针因此会产生迭代器失效因此的程序崩溃 b.删除时 在删除vi对象中一个奇数后迭代器依旧指向被删除元素的位置然后向下一个位置移动 由于erase()操作需要将元素向前挪动所以之前的迭代器实际上是失效的因此导致 5 5 5被错过 3.迭代器操作
由于vector是顺序存储的所以直接使用其元素指针做其迭代器typedef T* iterator;
因此对于iterator的操作如*(解引用)、、等实际上使用的底层库函数已经实现的对指针内置类型的操作符