很长一段时间没有动手编写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. 深入浅出单实例Singleton设计模式

    深入浅出单实例Singleton设计模式 陈皓 单实例Singleton设计模式可能是被讨论和使用的最广泛的一个设计模式了,这可能也是面试中问得最多的一个设计模式了.这个设计模式主要目的是想在整个系统 ...

  2. J2EE应用服务器计数器

    常用的J2EE应用服务器包括Weblogic.WebSphere和Tomcat等,以下是以WebLogic为例给出的计数器. 类别 计数器名称 计数器描述 JVM Heap Size JVM堆大小,该 ...

  3. 一步一步重写 CodeIgniter 框架 (3) —— 用面向对象重构代码

    前面两篇文章为了重点突出 CodeIgniter 框架的原理,程序的结构很乱,有很多全局变量,在这一课中我们采用面向对象的方法对原先代码进行重构. 到目前为止,程序主要完成的就是 URL 分析,并根据 ...

  4. android开发之蓝牙配对连接的方法

    最近在做蓝牙开锁的小项目,手机去连接单片机总是出现问题,和手机的连接也不稳定,看了不少蓝牙方面的文档,做了个关于蓝牙连接的小结. 在做android蓝牙串口连接的时候一般会使用 ? 1 2 3 4 5 ...

  5. 【linux】具体芯片MACHINE_START处理

    欢迎转载,转载时需保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http:// ...

  6. 日积月累:ScrollView嵌套ListView只显示一行

    在开发的过程当中,由于手机屏幕的大小的限制,我们经常需要使用滑动的方式,来显示更多的内容.在最近的工作中,遇见一个需求,需要将ListView嵌套到ScrollView中显示.于是乎有了如下布局: & ...

  7. CodeForces 462B Appleman and Card Game(贪心)

    题目链接:http://codeforces.com/problemset/problem/462/B Appleman has n cards. Each card has an uppercase ...

  8. Python 中的用户自定义类型

    Python中面向对象的技术 Python是面向对象的编程语言,自然提供了面向对象的编程方法.但要给面向对象的编程方法下一个定义,是很困难的.问题关键是理解对象 的含义.对象的含义是广泛的,它是对现实 ...

  9. poj3278Catch That Cow(BFS)

    Catch That Cow Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 37094   Accepted: 11466 ...

  10. Ubuntu环境下SSH的安装及使用

    Ubuntu环境下SSH的安装及使用 SSH是指Secure Shell,是一种安全的传输协议,Ubuntu客户端可以通过SSH访问远程服务器 .SSH的简介和工作机制可参看上篇文章SSH简介及工作机 ...