很长一段时间没有动手编写C++计划。无非就是模仿后STL对,虽然达不到标准STL该程序。但简单的功能来实现。

STL事实上,深刻:泛型编程、容器、算法、适配器...有的是内容能够学。以下是依据STL源代码。写的一个非常easy的vector,实现了部分接口。事实上vector还是相对非常easy的容器了,元素按在内存中连续排列,仅仅须要三个指针就能实现非常多的接口。另一个就是内存的分配,这里採用了一个C++提供的allocator配置器。所以分配起来还是蛮简单的,SGI版本号的STL中的配置器为了达到效率的极致,使用了另外的分配器。相当复杂。这里就没有写了。

#ifndef __MYVECTOR_H__
#define __MYVECTOR_H__ template <class T>
class Vector {
public:
typedef T value_type;
typedef value_type* iterator; // vector的迭代器就是原生指针
typedef value_type* pointer;
typedef value_type& reference;
typedef size_t size_type; public:
Vector() : start(NULL), finish(NULL), end_of_storage(NULL)
{
} Vector(size_type n, const value_type &value)
{
start = alloc.allocate(n);
end_of_storage = finish = start + n;
uninitialized_fill_n(start, n, value);
} Vector(size_type n)
{
start = alloc.allocate(n);
end_of_storage = finish = start + n;
uninitialized_fill_n(start, n, value_type());
} ~Vector()
{
// 顺序调用元素的析构函数
for (iterator i = start; i != finish; ++i)
alloc.destroy(i); // 销毁分配的空间
if (start != NULL)
alloc.deallocate(start, end_of_storage - start);
} iterator begin() const
{
return start;
} iterator end() const
{
return finish;
} size_type size() const
{
return end() - begin(); // 使用接口函数,包裹性更好
} size_type capacity() const
{
return end_of_storage - begin(); // 使用接口函数。包裹性更好
} bool empty() const
{
return begin() == end();
} // 返回的引用可被改动
reference front()
{
return *(begin());
} // 返回的引用可被改动
reference back()
{
return *(end() - 1);
} reference operator[] (const size_type n)
{
return *(begin() + n);
} const reference operator[] (const size_type n) const
{
return *(begin() + n);
} void push_back(const value_type &value)
{
if (finish == end_of_storage)
reallocate(); // 存储空间已满。则又一次分配内存
alloc.construct(finish, value);
++finish;
} void reallocate(); void pop_back()
{
--finish;
alloc.destroy(finish); // 析构最后一个函数,但不释放空间
} // 清除一个元素
iterator erase(iterator position)
{
if (position + 1 != finish)
copy(position + 1, finish, position);
--finish;
alloc.destroy(finish);
return position;
} // 清除一段元素
iterator erase(iterator first, iterator last)
{
if (first < start || last > finish)
throw exception("Invalid input."); copy(last, finish, first);
int len = last - first;
while (len--)
alloc.destroy(--finish);
return first;
} void clear()
{
erase(begin(), end());
} private:
iterator start;
iterator finish;
iterator end_of_storage; private:
static std::allocator<value_type> alloc; // 空间配置器。採用静态属性节省空间
}; template <class Type>
std::allocator<Type> Vector<Type>::alloc; template <class Type>
void Vector<Type>::reallocate()
{
size_type oldsize = size();
size_type newsize = 2 * (oldsize == 0 ? 1 : oldsize); // 分配新的内存空间
iterator newstart = alloc.allocate(newsize);
uninitialized_copy(start, finish, newstart); // 顺序调用每一个元素的析构函数
for (iterator i = start; i != finish; ++i)
alloc.destroy(i); // 销毁分配的空间,销毁之前主要检查是否为NULL
if (start != NULL)
alloc.deallocate(start, end_of_storage - start); // 更新下标
start = newstart;
finish = start + oldsize;
end_of_storage = start + newsize;
} #endif

insert操作应该算是最复杂的一个接口了,设计到元素的搬移、(可能)又一次分配内存等等,这里我仅仅实现了一个最简单的形式:

template <class Type>
void Vector<Type>::insert(iterator position, const value_type &value)
{
size_type diff = position - start; if (finish == end_of_storage)
reallocate(); position = start + diff; // 注意,这里不能使用copy。由于目的地最后一个位置还没有被构造,
// 赋值涉及析构操作,对未构造的对象进行析构,行为没有定义
alloc.construct(finish, *(finish - 1));
++finish;
copy_backward(position, finish - 1, finish); // 不能使用uninitialized_copy。由于这个函数是从前向后构造。这会造成覆盖
//uninitialized_copy(position, finish, position + 1); // 插入新对象,直接赋值就可以
*position = value;
}

測试程序:

int main()
{
Vector<int> v; v.push_back(1);
cout << "size = " << v.size() << endl;
cout << "capacity = " << v.capacity() << endl; v.push_back(2);
cout << "size = " << v.size() << endl;
cout << "capacity = " << v.capacity() << endl; v.push_back(3);
cout << "size = " << v.size() << endl;
cout << "capacity = " << v.capacity() << endl; v.push_back(4);
cout << "size = " << v.size() << endl;
cout << "capacity = " << v.capacity() << endl; v.push_back(5);
cout << "size = " << v.size() << endl;
cout << "capacity = " << v.capacity() << endl; Vector<int>::iterator iter1 = v.begin();
Vector<int>::iterator iter2 = iter1 + 3;
v.erase(iter1, iter2); cout << "size = " << v.size() << endl;
cout << "capacity = " << v.capacity() << endl; v.clear();
cout << "size = " << v.size() << endl;
cout << "capacity = " << v.capacity() << endl; v.push_back(123);
cout << "size = " << v.size() << endl;
cout << "capacity = " << v.capacity() << endl; for (Vector<int>::iterator iter = v.begin(); iter != v.end(); ++iter)
cout << *iter << endl; system("pause");
return 0;
}

执行结果:

參考:

《STL源代码剖析》

《C++ primer》

版权声明:本文博客原创文章。博客,未经同意,不得转载。

C++易vector的更多相关文章

  1. 几道c/c++练习题

    1.以下三条输出语句分别输出什么?[C易] char str1[] = "abc"; char str2[] = "abc"; const char str3[ ...

  2. C++开发工程师面试题库 50~100道

    51. New delete 与malloc free 的联系与区别?答案:都是在堆(heap)上进行动态的内存操作.用malloc函数需要指定内存分配的字节数并且不能初始化对象,new 会自动调用对 ...

  3. C++笔试题库之编程、问答题 150~200道

    151.写出判断ABCD四个表达式的是否正确, 若正确, 写出经过表达式中 a的值 int a = 4; (A)a += (a++); (B) a += (++a) ;(C) (a++) += a;( ...

  4. 嵌入式开发—C语言面试题

    嵌入式开发—C语言面试题 源地址:http://blog.csdn.net/xdx2ct1314/article/details/7358929   1. 用预处理指令#define 声明一个常数,用 ...

  5. CSharpGL(0)一个易学易用的C#版OpenGL

    +BIT祝威+悄悄在此留下版了个权的信说: CSharpGL(0)一个易学易用的C#版OpenGL CSharpGL是我受到SharpGL的启发,在整理了SharpGL,GLM,SharpFont等开 ...

  6. 剑指Offer——网易笔试之解救小易

    知识要点 首先介绍一下曼哈顿,曼哈顿是一个极为繁华的街区,高楼林立,街道纵横,从A地点到达B地点没有直线路径,必须绕道,而且至少要经C地点,走AC和 CB才能到达,由于街道很规则,ACB就像一个直角3 ...

  7. Java 常用数据结构深入分析(Vector、ArrayList、List、Map)

    线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构.这些类均在java.util包中.本文试图通过简单的描述,向读者阐述各个类的作用以 ...

  8. STL中vector,Map,Set的实现原理

    vector的数据安排以及操作方式,与array非常类似,两者唯一的区别是空间运用的灵活性,array是静态空间,一旦配置了就不能改变,如果你想要大一点的空间,就必须首先配置一块新空间,然后将原来的元 ...

  9. 细节!重点!易错点!--面试java基础篇(二)

    今天来给大家分享一下java的重点易错点第二部分,也是各位同学面试需要准备的,欢迎大家交流指正. 1.字符串创建与存储机制:当创建一个字符串时,首先会在常量池中查找是否已经有相同的字符串被定义,其判断 ...

随机推荐

  1. date、datetime、string的相互转换

    import datetime import time string转datetime str = '2012-11-19' date_time = datetime.datetime.strptim ...

  2. windows进程清理脚本

    公司统一配的笔记本Thinkpad T440p,超级难用,常常内存占满.硬盘卡死,还管不了机!心里那个不爽啊!哎,不说了. 自己写了个脚本,用来强制关闭不须要的进程. 脚本例如以下: -------- ...

  3. Swift实现糗事百科Demo(实战项目)

    在这里,你将会学习到解析JSON数据,网络请求功能,动态调整cell内容等功能!!! 最终的结果 是这样的,项目相对简单,很适合入门!下面让我们一起开始教程之旅吧! 1.先看下项目工程结构: 第一步: ...

  4. PHP - 类库

    常用的PHP类库,PHP开发者必备[转] PHP开发者常用的PHP类库和组件 PDF 生成器 FPDF - 这量一个可以让你生成PDF的纯PHP类库. Excel 相关 你的站点需要生成Excel?没 ...

  5. 【Lucene】近实时搜索

    近实时搜索:可以使用一个打开的IndexWriter快速搜索索引的变更内容,而不必首先关闭writer,或者向该writer提交:这是2.9版本之后推出的新功能. 代码示例(本例参考<Lucen ...

  6. 基于visual Studio2013解决面试题之1309求子集

     题目

  7. python算法之二分查找

    说明:大部分代码是在网上找到的,好几个代码思路总结出来的 通常写算法,习惯用C语言写,显得思路清晰.可是假设一旦把思路确定下来,并且又不想打草稿.想高速写下来看看效果,还是python写的比較快.也看 ...

  8. EasyUI - DataGrid 组建 - [ 新增功能 ]

    效果: html代码: <div> <!--使用JS加载方式--> <table id="tab"></table> <!-- ...

  9. 实现长按删除QListWidget的Item

    原地址:http://blog.sina.com.cn/s/blog_5c70dfc80100r99u.html 要想长按删除QListWidget的Item,必须重写鼠标事件,所以需要继承QList ...

  10. N-Queens And N-Queens II [LeetCode] + Generate Parentheses[LeetCode] + 回溯法

    回溯法 百度百科:回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步又一次选择,这样的走不通就退回再走的技术为回溯法 ...