动手实现自己的 STL 容器 《1》---- vector
本文参考了侯捷的 《STL 源码分析》一书,出于兴趣,自行实现了简单的 vector 容器。
之后会陆续上传 list, deque 等容器的代码,若有错误,欢迎留言指出。
vector 容易实现的几点注意事项:
1. 由于vector 是动态数组。
出于效率的考虑,在往vector 中加入元素时,内存的扩展遵循的规则是:
1> 如果当前可用内存不够,开 2倍大的内存,将原来的数组复制到新数组中,撤销原来的数组。
2> 加入新的元素
2. 通常当我们 int *p = new int(1)时, new 其实做了两件事情: 1> 分配内存 2>在分配的内存中调用类的构造函数。
出于效率的考虑,在 vector 的内存管理中,我们将这两个操作分开。
C++ 提供了 模板类 allocator 来实现上述的功能。
3. vector 中三个指针,分别是 start, finish, end_of_storage;
[start, finish) 就是数组元素;
[finish, end_of_storage) 是预先分配的空间(还没有调用构造函数)
参考书籍:
1. C++ primer, Lippman
2. STL 源码分析, 侯捷
// Last Update:2014-04-11 15:44:44
/**
* @file vector.h
* @brief a simple vector class
* @author shoulinjun@126.com
* @version 0.1.00
* @date 2014-04-09
*/ #ifndef MY_VECTOR_H
#define MY_VECTOR_H #include <iostream>
#include <algorithm>
#include <memory> template<class T>
void destroy(T* pointer)
{
pointer->~T();
} template<class ForwardIterator>
void destroy(ForwardIterator first, ForwardIterator last)
{
for(ForwardIterator it = first; it != last; ++ it)
{
destroy(&*it);
}
} template<class T>
class MyVector
{
public:
typedef T value_type;
typedef T* iterator;
typedef const T*const_iterator;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type; MyVector();
MyVector(size_type n, T value = T());
MyVector(iterator begin, iterator end);
~MyVector(); //copy control
MyVector(const MyVector&);
MyVector& operator=(const MyVector&); bool empty() const { return begin() == end(); }
size_type size() const {return (size_type)(finish - start);}
size_type capacity() const {return (size_type)(end_of_storage - start);} iterator begin() { return start; }
const_iterator begin() const{ return start; }
iterator end() { return finish;}
const_iterator end() const{ return finish; } reference operator[](size_type i){return *(start + i);}
const_reference operator[](size_type i)const {return *(start + i);} void insert(iterator position, size_type n, const T& value);
void push_back(const T& value);
void pop_back(); void erase(iterator first, iterator last);
void clear(); void reserve(size_type n);
protected:
iterator start; //空间的头
iterator finish; //空间的尾
iterator end_of_storage; //可用空间的尾巴
private:
static std::allocator<T> alloc; // object to get raw memory
}; // static class member needed to be defined outside of class
template<class T>
std::allocator<T> MyVector<T>::alloc; // default constructor
template<class T>
MyVector<T>::MyVector()
: start(NULL), finish(NULL), end_of_storage(NULL)
{
} template<class T>
MyVector<T>::MyVector(size_type n, T value)
{
start = alloc.allocate(n);
end_of_storage = finish = start + n; for(iterator i=start; i!=finish; ++i)
alloc.construct(i, value);
} template<class T>
MyVector<T>::MyVector(iterator begin, iterator end)
{
const size_type n = end - begin;
/* allocate space */
start = alloc.allocate(n);
finish = end_of_storage = start + n; /* call constructor */
std::uninitialized_copy(begin, end, start);
} template<class T>
MyVector<T>::~MyVector()
{
/* call destructor */
::destroy(start, finish); /* free space */
alloc.deallocate(start, end_of_storage - start);
} // copy control
template<class T>
MyVector<T>::MyVector(const MyVector& rhs)
{
start = alloc.allocate(rhs.capacity());
std::uninitialized_copy(rhs.start, rhs.finish, start);
finish = start + (rhs.finish - rhs.start);
end_of_storage = start + (rhs.end_of_storage - rhs.start);
} template<class T>
MyVector<T>& MyVector<T>::operator=(const MyVector& rhs)
{
start = alloc.allocate(rhs.capacity());
std::uninitialized_copy(rhs.start, rhs.finish, start);
finish = start + rhs.finish - rhs.start;
end_of_storage = start + rhs.end_of_storage - rhs.start; return *this;
} template<class T>
void MyVector<T>::insert(iterator position, size_type n, const T& value)
{
if(n <= end_of_storage - finish)
{/* enough memory */
if(n <= finish - position)
{
std::uninitialized_copy(finish-n, finish, finish);
std::copy(position, finish-n, position+n);
std::fill_n(position, n, value);
}
else
{
std::uninitialized_fill_n(finish, n - (finish - position), value);
std::uninitialized_copy(position, finish, position + n);
std::fill(position, finish, value);
}
finish += n;
}
else
{/* reallocate */
pointer new_start(NULL), new_finish(NULL);
size_type old_type = end_of_storage - start;
size_type new_size = old_type + std::max(old_type, n);
new_start = alloc.allocate(new_size); // copy old vector to new vector
new_finish = std::uninitialized_copy(start, position, new_start);
std::uninitialized_fill_n(new_finish, n, value);
new_finish += n;
new_finish = std::uninitialized_copy(position, finish, new_finish); alloc.deallocate(start, end_of_storage - start); start = new_start;
finish = new_finish;
end_of_storage = new_start + new_size;
}
} template<class T>
void MyVector<T>::push_back(const T &value)
{
insert(end(), 1, value);
} template<class T>
void MyVector<T>::pop_back()
{
alloc.destroy(--finish);
} template<class T>
void MyVector<T>::erase(iterator first, iterator last)
{
iterator old_finish = finish;
finish = std::copy(last, finish, first);
::destroy(finish, old_finish);
} template<class T>
void MyVector<T>::clear()
{
erase(start, finish);
} template<class T>
void MyVector<T>::reserve(size_type n)
{
if(capacity() < n)
{
iterator new_start = alloc.allocate(n);
std::uninitialized_copy(start, finish, new_start); ::destroy(start, finish);
alloc.deallocate(start, size()); const size_type old_size = finish - start;
start = new_start;
finish = new_start + old_size;
end_of_storage = new_start + n;
}
} #endif /*MY_VECTOR_H*/
动手实现自己的 STL 容器 《1》---- vector的更多相关文章
- STL容器之一vector
STL中最简单也是最有用的容器之一是vector<T>类模板,称为向量容器,是序列类型容器中的一种. 1.vector<T> 对象的基本用法(1)声明:vector<ty ...
- STL 容器(vector 和 list )
1.这个容器的知识点比较杂 迭代器的理解: 1.erase()函数的返回值,它的迭代器在循环遍历中的奇特之处: #define _CRT_SECURE_NO_WARNINGS #include < ...
- 动手实现自己的 STL 容器《2》---- list
1. 序: 本文参考了侯捷的 <STL 源码分析>一书,出于兴趣,自行实现了简单的 list 容器. 学习了 STL 的 list 容器的源代码,确实能够提高写链表代码的能力.其中的 so ...
- STL—— 容器(vector)元素的删除
1. clear() 将整个 vector 都删除 使用 vectorname.clear() 可以将整个vector 中的元素全部删除,但是内存不会释放,如下代码: 1 #include <i ...
- STL—— 容器(vector)数据插入insert()方法 的返回值
vector 容器下的 insert() 方法拥有返回值,由于insert() 方法拥有4种重载函数,他的返回值不尽相同. 第一种,插入单个元素后的返回值: 1 #include <iostre ...
- STL—— 容器(vector)的数据插入之 insert()
vector 容器可以使用 vectorName.insert() 方法插入元素,vectorName.insert() 函数一共有4种重载方法: 第一种 insert() 用法:在指定地址插入单个元 ...
- STL—— 容器(vector)的各种功能方法
1. 获取容器的元素个数 size() 使用 vectorName.size() 可以输出这个容器中类型的个数,如下代码: 1 #include <iostream> 2 #include ...
- STL—— 容器(vector)的数据写入、修改和删除
1. 通过 push_back() 尾部增加一个元素 : vector 可以通过 "push_back " 写入数据,通过 push_back 可以将数据直接写入至 vector ...
- STL—— 容器(vector)的内存分配,声明时的普通构造&带参构造
vector 的几种带参构造 & 初始化与内存分配: 1. 普通的带参构造: vector 的相关对象可以在声明时通过 vector 的带参构造函数进行内存分配,如下: 1 #include ...
随机推荐
- 如何生成DLL文件
1.打开项目工程,点击Rebuild 2.Rebuild成功后,打开该项目所在文件目录 3.在路径里,在bin->Debug文件下可以看到刚生成成功的dll文件.
- laravel框架总结(五) -- 服务提供者(提及契约Contracts)
首先理解两个概念 1.契约:一组定义了框架核心服务的接口 2.服务提供者:所有 Laravel 应用程序启动的中心所在. 包括你自己的应用程序,以及所有的 Laravel 核心服务,都是通过服务提供者 ...
- javascript 面向对象(转)
1.使用[]调用对象的属性和方法 function User() { this.age = 21; this.sex = "男?"; } var user = new User() ...
- 有限状态机(Python)
有限状态机(Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型.FSM是一种算法思想,简单而言,有限状 ...
- Key Figure中的Aggregation决定了DSO/CUBE转换规则中的Aggregation合计方式
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- qq2440启动linux后出现错误提示request_module: runaway loop modprobe binfmt-464c
1.情景: 编译busybox时加了make CROSS_COMPILE=arm-linux-,但是还是出现了此情况! 2.解决方案如下: 配置busybox时,在配置中发现busybox setti ...
- 简单SSM配置详解
SSM:spring+springMVC+Mybatis 学习网友的http://www.cnblogs.com/invban/p/5133257.html,并对其进行了详细的解说. 源码下载:htt ...
- php : 匿名函数(闭包) [一]
摘自: http://www.cnblogs.com/starlion/p/3894578.html 一:匿名函数 (在php5.3.0 或以上才能使用) php中的匿名函数(Anonymous fu ...
- python 中date datetime time 与str的互转
以下全部引入 form datetime import datetime, timedelta import time 一.time 转str 二.datetime 转 str str_date = ...
- hdu4987A simple probability problem.(凸包)
链接 多校的最后一场,当时没看懂题意,看题目还以为是概率问题就没深看. 官方题解 对于他说的第一种,考虑长为L的线段 概率为2L/(pi*d), 可以理解,下面的就不知道在说啥了.. 按我初始的想法想 ...