《STL系列》之vector原理及实现
最近忙得蛋疼,但还是想写点属于自己的东西。也不知道写点啥,最后决定试着自己实现STL中常用的几个集合,一来加深自己对STL的理解,二来看看自己是否有这个能力实现。实现目标就是:1能和STL兼容;2最大化的实现STL中的接口并保持一致。即将STL中的集合换成我写的也能用。这篇博客介绍的是vector的原理及实现。
先把vector的大致实现说一下,后面会给出完整的源码。
新增元素:Vector通过一个连续的数组存放元素,如果集合已满,在新增数据的时候,就要分配一块更大的内存,将原来的数据复制过来,释放之前的内存,在插入新增的元素。插入新的数据分在最后插入push_back和通过迭代器在任何位置插入,这里说一下通过迭代器插入,通过迭代器与第一个元素的距离知道要插入的位置,即int index=iter-begin()。这个元素后面的所有元素都向后移动一个位置,在空出来的位置上存入新增的元素。
void insert(const_iterator iter,const T& t )
{
int index=iter-begin();
if (index<size_)
{
if (size_==capacity_)
{
int capa=calculateCapacity();
newCapacity(capa);
}
memmove(buf+index+,buf+index,(size_-index)*sizeof(T));
buf[index]=t;
size_++;
}
}
删除元素:删除和新增差不多,也分两种,删除最后一个元素pop_back和通过迭代器删除任意一个元素erase(iter)。通过迭代器删除还是先找到要删除元素的位置,即int index=iter-begin();这个位置后面的每个元素都想前移动一个元素的位置。同时我们知道erase不释放内存只初始化成默认值。
删除全部元素clear:只是循环调用了erase,所以删除全部元素的时候,不释放内存。内存是在析构函数中释放的。
iterator erase(const_iterator iter)
{
int index=iter-begin();
if (index<size_ && size_>)
{
memmove(buf+index ,buf+index+,(size_-index)*sizeof(T));
buf[--size_]=T();
}
return iterator(iter);
}
迭代器iteraotr是STL的一个重要组成部分,通过iterator可以很方便的存储集合中的元素.STL为每个集合都写了一个迭代器, 迭代器其实是对一个指针的包装,实现一些常用的方法,如++,--,!=,==,*,->等, 通过这些方法可以找到当前元素或是别的元素. vector是STL集合中比较特殊的一个,因为vector中的每个元素都是连续的,所以在自己实现vector的时候可以用指针代替,如typedef T* iterator;typedef const T* const_iterator,如果STL中的函数能方便的操作自己写的集合,实现的迭代器最好继承std::iterator<std::forward_iterator_tag,T>。我实现vector的迭代器大概是这个样子:
template<typename T>
class viterator:public std::iterator<std::forward_iterator_tag,T>{}
后面会给出完整的代码,std::iterator<std::forward_iterator_tag,T>的源码如下:
template<class _Category,
class _Ty,
class _Diff = ptrdiff_t,
class _Pointer = _Ty *,
class _Reference = _Ty&>
struct iterator
{ // base type for all iterator classes
typedef _Category iterator_category;
typedef _Ty value_type;
typedef _Diff difference_type;
typedef _Diff distance_type; // retained
typedef _Pointer pointer;
typedef _Reference reference;
};
Iterator其中没有任何成员,只是定义了一组类型,所以继承它并不会让你的struct变大,这组类型是STL的内部契约,STL中的函数假设每个迭代器都定义了这些类型,所以只要你的迭代器定义了这些类型,就可以和STL函数集合一起使用。
我的vector实现源码如下:
#ifndef _CVECTOR_H_
#define _CVECTOR_H_ namespace cth
{
class NoCopy
{
public:
inline NoCopy(){}
NoCopy(const NoCopy&);
NoCopy& operator=(const NoCopy&);
}; template<typename T>
class viterator:public std::iterator<std::forward_iterator_tag,T>
{
public:
viterator()
{
t=NULL;
}
viterator(T* t_)
{
t=t_;
}
viterator(const viterator& other)
{
t=other.t;
}
viterator& operator=(const viterator& other)
{
t=other.t;
return *this;
} viterator& operator++()
{
t++;
return *this;
}
viterator operator++(int)
{
viterator iter=*this;
t++;
return iter;
}
viterator operator+(int count)
{
viterator iter=*this;
iter.t+=count;
return iter;
}
viterator& operator--()
{
t--;
return *this;
}
viterator operator--(int)
{
viterator iter=*this;
t--;
return iter;
}
viterator operator-(int count)
{
viterator iter=*this;
iter.t-=count;
return iter;
} int operator-(const viterator& other)
{
return t-other.t;
}
int operator-(const viterator& other)const
{
return t-other.t;
} T& operator*()
{
return *t;
}
const T& operator*() const
{
return *t;
} T* operator->()
{
return t;
}
const T* operator->() const
{
return t;
} inline bool operator!=(const viterator& other)
{
return t!=other.t;
}
inline bool operator!=(const viterator& other)const
{
return t!=other.t;
} inline bool operator==(const viterator& other)
{
return t==other.t;
}
inline bool operator==(const viterator& other)const
{
return t==other.t;
} inline bool operator<(const viterator& other)
{
return t<other.t;
}
inline bool operator<(const viterator& other)const
{
return t<other.t;
} inline bool operator<=(const viterator& other)
{
return t<=other.t;
}
inline bool operator<=(const viterator& other)const
{
return t<=other.t;
} inline bool operator>(const viterator& other)
{
return t>other.t;
}
inline bool operator>(const viterator& other)const
{
return t>other.t;
} inline bool operator>=(const viterator& other)
{
return t>=other.t;
}
inline bool operator>=(const viterator& other)const
{
return t>=other.t;
}
private:
T* t;
}; template<typename T>
class cvector:public NoCopy
{
public:
typedef viterator<T> iterator;//viterator<T>就是对一个指针的包装,所以完全可以用T*代替viterator <T>
typedef const viterator<T> const_iterator; //typedef T* iterator;
//typedef const T* const_iterator;
cvector()
{
initData();
}
cvector(int capa,const T& val=T())
{
initData(capa);
newCapacity(capacity_);
for (int i=;i<size_;i++)
buf[i]=val;
}
cvector(const_iterator first,const_iterator last)
{
initData(last-first);
newCapacity(capacity_);
iterator iter=iterator(first);
int index=;
while(iter!=last)
buf[index++]=*iter++;
} ~cvector()
{
if (buf)
{
delete[] buf;
buf=NULL;
}
size_=capacity_=;
}
void clear()
{
if (buf)
erase(begin(),end());
} void push_back(const T& t)
{
if (size_==capacity_)
{
int capa=calculateCapacity();
newCapacity(capa);
}
buf[size_++]=t;
}
void pop_back()
{
if (!empty())
erase(end() - );
} int insert(const_iterator iter,const T& t )
{
int index=iter-begin();
if (index<=size_)
{
if (size_==capacity_)
{
int capa=calculateCapacity();
newCapacity(capa);
}
memmove(buf+index+,buf+index,(size_-index)*sizeof(T));
buf[index]=t;
size_++;
}
return index;
}
iterator erase(const_iterator iter)
{
int index=iter-begin();
if (index<size_ && size_>)
{
memmove(buf+index ,buf+index+,(size_-index)*sizeof(T));
buf[--size_]=T();
}
return iterator(iter);
} iterator erase(const_iterator first,const_iterator last)
{
iterator first_=iterator(first);
iterator last_=iterator(last);
while(first_<=last_--)
erase(first_);
return iterator(first_);
} T& front()
{
assert(size_>);
return buf[];
}
T& back()
{
assert(size_>);
return buf[size_-];
}
T& at(int index)
{
assert(size_>);
return buf[index];
}
T& operator[](int index)
{
assert(size_> && index>= && index<size_);
return buf[index];
} bool empty() const
{
return size_==;
}
int size() const
{
return size_;
}
int capacity() const
{
return capacity_;
} iterator begin()
{
return iterator(&buf[]);
}
iterator end()
{
return iterator(&buf[size_]);
} private:
void newCapacity(int capa)
{
capacity_=capa;
T* newBuf=new T[capacity_];
if (buf)
{
memcpy(newBuf,buf,size_*sizeof(T));
delete [] buf;
}
buf=newBuf;
} inline int calculateCapacity()
{
return capacity_*/+ ;
} inline void initData(int capa)
{
buf=NULL;
size_=capacity_=capa>?capa:;
}
int size_;
int capacity_ ;
T* buf;
}; struct Point
{
Point(int x_=,int y_=):x(x_),y(y_){}
int x,y;
}; bool operator<(const Point& p1,const Point& p2)
{
if(p1.x<p2.x)
{
return true;
}else if(p1.x>p2.x)
{
return false;
}
return p1.y<p2.y;
} void cvectorTest()
{
cvector<Point> vect;
for (int i=;i<;i++)
{
Point p(i,i);
vect.push_back(p);
} cvector<Point>::iterator iter=vect.begin();
while (iter!=vect.end())
{
cout<< "[" << iter->x << " " << iter->y <<"], ";
++iter;
}
iter=vect.begin()+;
vect.insert(iter,Point(,));
iter=vect.end()-;
vect.insert(iter,Point(,));
cout<<endl<<endl<<"插入两个元素后:"<<endl;
iter=vect.begin();
while (iter!=vect.end())
{
cout<< "[" << iter->x << " " << iter->y <<"], ";
++iter;
}
std::sort(vect.begin(),vect.end());
cout<<endl<<endl<<"排序后:"<<endl;
iter=vect.begin();
while (iter!=vect.end())
{
cout<< "[" << iter->x << " " << iter->y <<"], ";
++iter;
}
vect.erase(vect.begin()+);
vect.erase(vect.begin()+);
cout<<endl<<endl<<"删除之前新增的两个元素"<<endl;
iter=vect.begin();
while (iter!=vect.end())
{
cout<< "[" << iter->x << " " << iter->y <<"], ";
++iter;
}
vect.clear();
cout<<endl<<endl<<"执行clear之后"<<endl;
cout<<"size="<<vect.size()<<",capacity="<<vect.capacity(); cvector<Point> vect1;
for (int i=;i<;i++)
{
Point p(i,i);
vect1.push_back(p);
}
cout<<endl<<endl<<"从别的cvector复制数据:"<<endl; cvector<Point> vect2(vect1.begin(),vect1.end());
vect2.pop_back();
vect2.pop_back();
for(int i=;i<vect2.size();i++)
{
cout<<"["<<vect2[i].x<<","<<vect2[i].y<<"], ";
} cout<<endl;
} } #endif
实例代码级运行结果如下:
struct Point
{
Point(int x_=,int y_=):x(x_),y(y_){}
int x,y;
}; bool operator<(const Point& p1,const Point& p2)
{
if(p1.x<p2.x)
{
return true;
}else if(p1.x>p2.x)
{
return false;
}
return p1.y<p2.y;
} void cvectorTest()
{
cvector<Point> vect;
for (int i=;i<;i++)
{
Point p(i,i);
vect.push_back(p);
} cvector<Point>::iterator iter=vect.begin();
while (iter!=vect.end())
{
cout<< "[" << iter->x << " " << iter->y <<"], ";
++iter;
}
iter=vect.begin()+;
vect.insert(iter,Point(,));
iter=vect.end()-;
vect.insert(iter,Point(,));
cout<<endl<<endl<<"插入两个元素后:"<<endl;
iter=vect.begin();
while (iter!=vect.end())
{
cout<< "[" << iter->x << " " << iter->y <<"], ";
++iter;
}
std::sort(vect.begin(),vect.end());
cout<<endl<<endl<<"排序后:"<<endl;
iter=vect.begin();
while (iter!=vect.end())
{
cout<< "[" << iter->x << " " << iter->y <<"], ";
++iter;
}
vect.erase(vect.begin()+);
vect.erase(vect.begin()+);
cout<<endl<<endl<<"删除之前新增的两个元素"<<endl;
iter=vect.begin();
while (iter!=vect.end())
{
cout<< "[" << iter->x << " " << iter->y <<"], ";
++iter;
}
vect.clear();
cout<<endl<<endl<<"执行clear之后"<<endl;
cout<<"size="<<vect.size()<<",capacity="<<vect.capacity(); cvector<Point> vect1;
for (int i=;i<;i++)
{
Point p(i,i);
vect1.push_back(p);
}
cout<<endl<<endl<<"从别的cvector复制数据:"<<endl; cvector<Point> vect2(vect1.begin(),vect1.end());
vect2.pop_back();
vect2.pop_back();
for(int i=;i<vect2.size();i++)
{
cout<<"["<<vect2[i].x<<","<<vect2[i].y<<"], ";
} cout<<endl;
}
之后还会有list,set,map等的实现,敬请期待......
《STL系列》之vector原理及实现的更多相关文章
- 《STL系列》之map原理及实现
上一篇文章<STL系列>之vector原理及实现,介绍了vector的原理及实现,这篇文章介绍map的原理及实现.STL实现源码下载.STL中map的实现是基于RBTree的,我在实现的时 ...
- Java 集合系列 05 Vector详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- [知识点]C++中STL容器之vector
零.STL目录 1.容器之map 2.容器之vector 3.容器之set 一.前言 关于STL和STL容器的概念参见STL系列第一篇——map(见上).今天介绍第二个成员——vector. 二.用途 ...
- [STL] STL各容器实现原理
STL共有六大组件1.容器 2.算法 3.迭代器 4.仿函数 6.适配器 STL容器的实现原理 STL来管理数据十分方便,省去了我们自己构建数据结构的时间.其实,STL的实现也是基于我们常见的数据结构 ...
- java基础解析系列(七)---ThreadLocal原理分析
java基础解析系列(七)---ThreadLocal原理分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)-- ...
- 转:用STL中的vector动态开辟二维数组
用STL中的vector动态开辟二维数组 源代码:#include <iostream>#include <vector>using namespace std;int mai ...
- java基础解析系列(六)---注解原理及使用
java基础解析系列(六)---注解原理及使用 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---Integer缓存及 ...
- STL中的Vector相关用法
STL中的Vector相关用法 标准库vector类型使用需要的头文件:#include <vector>. vector 是一个类模板,不是一种数据类型,vector<int> ...
- (转)C++ STL中的vector的内存分配与释放
C++ STL中的vector的内存分配与释放http://www.cnblogs.com/biyeymyhjob/archive/2012/09/12/2674004.html 1.vector的内 ...
- C++STL中的vector的简单实用
[原创] 使用C++STL中的vector, #include <stdio.h> #include<stdlib.h> #include<vector> usin ...
随机推荐
- win10使用Composer-Setup安装Composer以及使用Composer安装Yii2最新版
1:下载 ca-bundle.crt和cacert.pem 将这两个文件放在php目录下 2:php.ini中添加上述两个文件的路径 curl.cainfo=C:/xampp/php/ca-bundl ...
- UIView的剖析(转)
转自:http://blog.csdn.net/mengtnt/article/details/6716289 前面说过UIViewController,但是UIView也是在MVC中非常重要的一层 ...
- day7----面向对象编程进阶
本节内容: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 静态方法 它与类唯一的关联就是需要通过类名来调用这个方法 #静态方法实际跟类没关系,不 ...
- RDBMS,memcache
1.RDBMS即关系数据库管理系统(Relational Database Management System),是将数据组织为相关的行和列的系统,而管理关系数据库的计算机软件就是关系数据库管理系统, ...
- C#设计模式(15)——命令模式(Command Pattern)
一.前言 之前一直在忙于工作上的事情,关于设计模式系列一直没更新,最近项目中发现,对于设计模式的了解是必不可少的,当然对于设计模式的应用那更是重要,可以说是否懂得应用设计模式在项目中是衡量一个程序员的 ...
- ASP.NET Web API 跨域访问
自定义特性 要在WebApi中实现JSONP,一种方式是实现自定义特性 http://stackoverflow.com/questions/9421312/jsonp-with-asp-net-w ...
- Sqoop-1.4.6.bin__hadoop-2.0.4-alpha 环境搭建
一.Sqoop 环境搭建 1.下载安装包及解压 sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz 1)拷贝sqoop-1.4.6.bin__hadoop-2 ...
- PHP爬虫技术(一)
摘要:本篇文章介绍PHP抓取网页内容技术,利用PHP cURL扩展获取网页内容,还可以抓取网页头部,设置cookie,处理302跳转. 一.cURL安装 采用源码安装PHP时,需要在configure ...
- Spring - 初始化spring容器
2016.01.12 学习linux内核的过程中发现变相的提升了自己的工程能力.以前觉得spring这些东西很复杂麻烦.然而,学了linux内核再看这些东西,发现好简单. 学习spring首先就要学习 ...
- Vue学习笔记1
目录 前言 1.vue和avalon一样,都不支持VM初始时不存在的属性 2.input元素中属性与v-model同时存在以属性为优先 3.VM中的函数放到data属性和methods属性中的区别,以 ...