您的位置:首页 > 其它

动手实现自己的 STL 容器 《1》---- vector

2014-04-11 15:58 316 查看
本文参考了侯捷的 《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*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: