之前用数组简单实现了vector,看了primer之后,用allocator类再次简单实现了vector,和数组相比较,allocator类分配内存和构造对象更容易。。

具体的代码:(有问题请指出)

1 Vector.h类:

#ifndef VECTOR_H
#define VECTOR_H
#include <memory> //allocator类
#include<iostream>
#include<initializer_list>
using namespace std;
template <typename T>
class Vector
{
 public:
    typedef T* iterator;
    typedef const T* const_iterator;

    Vector() : elements(nullptr), first_free(nullptr), cap(nullptr) {} 
    Vector(std::initializer_list<T> l);
    Vector(int initsize, T value);
    Vector(iterator b, iterator e);

    Vector(const Vector&);  //拷贝构造函数
    Vector& operator=(const Vector&);  //拷贝赋值运算符
    ~Vector();//析构函数

    //新标准
    Vector(Vector&&);//移动构造函数
    Vector& operator=(Vector&&);//移动赋值运算符
    
    bool empty()const  { return first_free == elements; }
    size_t size() const { return first_free - elements; }
    size_t capacity() const { return cap - elements; }
    iterator begin() const{ return elements; }
    iterator end() const { return first_free; }
    const_iterator cbegin() const { return elements; }
    const_iterator cend() const { return first_free; }

    bool operator==(const Vector<T>& rhs);
    bool operator!=(const Vector<T>& rhs);

    void reserve(size_t new_cap);
    void resize(size_t count);
    void resize(size_t count, const T& s);

    T &operator[](int index);
    const T &operator[](int index) const;
    T &front();
    const T &front() const;
    T &back();
    const T &back() const;
    void push_back(const T&);
    iterator insert(iterator b, const T& value);
    void pop_back() { first_free--; alloc.destroy(first_free); }
    iterator erase(iterator b);
    void clear();

private:
    std::pair<T*, T*> alloc_n_copy(const T*, const T*);    //分配内存,拷贝一定范围中的元素
    void free();    //析构对象和释放内存
    void chk_n_alloc() { if (size() == capacity()) reallocate(); }
    void reallocate();
    void alloc_n_move(size_t new_cap);

private:
    T *elements;     
    T *first_free;                    //指向尾后元素
    T *cap;                           //指向内存末尾之后的位置
    static std::allocator<T> alloc;
};
template <typename T>
std::allocator<T> Vector<T>::alloc;

template<typename T>
Vector<T>::Vector(std::initializer_list<T> l)     //列表初始化
{
    T* const newData = alloc.allocate(l.size());   //常量指针
    T* p = newData;
    for (const auto &t : l)
        alloc.construct(p++, t);
    elements = newData;
    first_free = cap = elements + l.size();
}
template<typename T>
Vector<T>::Vector(int initsize, T value)
{
    T* const data = alloc.allocate(initsize);
    T* p = data;
    //uninitialized_fill_n(p, initsize, value) //可以用下面的for语句代替
    for (int i = 0; i != initsize; ++i)
        alloc.construct(p++, value);
        elements = data;
    first_free = cap = elements + initsize;
}
template<typename T>
Vector<T>::Vector(iterator b, iterator e)
{
    int num = e - b;
    T* const data = alloc.allocate(num);
    T* p = data;
    //uninitialized_copy(b, e, p);   //这里传p是因为怕要求data指针发生变化,可以用for语句代替,作用是一样的
    for (; b != e; ++b)
        alloc.construct(p++, *b);
    elements = data;
    first_free = cap = elements + num;
}
template <typename T>
std::pair<T*, T*>
Vector<T>::alloc_n_copy(const T* b, const T* e)
{
    auto data = alloc.allocate(e - b);
    auto olddata=data;
    for (; b != e; ++b)
        alloc.construct(data++, *b);
    //return  make_pair( data, std::uninitialized_copy(b, e, data)) ;  //新标准,返回的是新分配的内存中范围迭代器
    return make_pair(olddata, data);
}
template <typename T>
void Vector<T>::free()
{
    if (elements)
    {
        for (auto p = first_free; p != elements;)
            alloc.destroy(--p);   //析构对象
        alloc.deallocate(elements, cap - elements);  //释放内存
    }
}
template <typename T>
Vector<T>::Vector(const Vector &rhs)   //拷贝构造函数
{
    auto newdata = alloc_n_copy(rhs.begin(), rhs.end());
    elements = newdata.first;
    first_free = cap = newdata.second;
}
template <typename T>
Vector<T>::~Vector()
{
    free();
}
template <typename T>
Vector<T>& Vector<T>::operator=(const Vector &rhs)
{
    auto data = alloc_n_copy(rhs.begin(), rhs.end());
    free();
    elements = data.first;
    first_free = cap = data.second;
    return *this;
}
//移动构造函数
template <typename T>
Vector<T>::Vector(Vector &&s) :elements(s.elements), first_free(s.first_free), cap(s.cap)
{

    s.elements = s.first_free = s.cap = nullptr;
}
//移动赋值运算符
template <typename T>
Vector<T>& Vector<T>::operator = (Vector &&rhs)
{
    if (this != &rhs) {
        free();
        elements = rhs.elements;
        first_free = rhs.first_free;
        cap = rhs.cap;
        rhs.elements = rhs.first_free = rhs.cap = nullptr;
    }
    return *this;
}
template<typename T>
bool Vector<T>::operator==(const Vector<T>& rhs)
{
    if (first_free - elements == rhs.first_free - rhs.elements)
    {
        int cnt = 0;
        for (T *p = elements, *q = rhs.elements; p != first_free&& q != rhs.first_free; ++p, ++q)
            if (*p ==*q)
                ++cnt;
        if (cnt == first_free - elements)
            return true;
    }
    return false;
}
template<typename T>
bool Vector<T>::operator!=(const Vector<T>& rhs)
{
    return !(*this == rhs);
}

//分配new_cap个的内存空间。
template <typename T>
void Vector<T>::alloc_n_move(size_t new_cap)
{
    auto newdata = alloc.allocate(new_cap);
    auto dest = newdata;
    T* elem = elements;
    for (size_t i = 0; i != this->size(); ++i)
        alloc.construct(dest++, std::move(*elem++));
    free();
    elements = newdata;
    first_free = dest;
    cap = elements + new_cap;
}

template <typename T>
void Vector<T>::reallocate()
{
    auto newcapacity = size() ? 2 * size() : 1;
    alloc_n_move(newcapacity);
}

template <typename T>
void Vector<T>::reserve(size_t new_cap)
{
    if (new_cap <= capacity())
        return;
    alloc_n_move(new_cap);
}
template <typename T>
void Vector<T>::resize(size_t count, const T &s)
{
    if (count > size())
    {
        if (count > capacity())
            reserve(count * 2);
        for (size_t i = size(); i != count; ++i)
            alloc.construct(first_free++, s);
    }
    else if (count < size())
    {
        while (first_free != elements + count)
            alloc.destroy(--first_free);    //析构对象
    }
}
template <typename T>
void Vector<T>::resize(size_t count)
{
    resize(count, T());
}
template<typename T>
T &Vector<T>::operator[](int index)
{
    if (index < 0 || index >= size())
    {
        cout << "out of memory" << endl;
        exit(0);
    }
    return elements[index];
}
template<typename T>
const T &Vector<T>::operator[] (int index) const

{
    if (index < 0 || index >= size())
    {
        cout << "out of memory" << endl;
        exit(0);
    }
    return elements[index];
}
template<typename T>
T& Vector<T>::front()
{
    if (!this->empty())
        return elements[0];
}
template<typename T>
const T& Vector<T>::front() const
{
    if (!this->empty())
        return elements[0];
}
template<typename T>
T& Vector<T>::back()
{
    if (!this->empty())
        return elements[size() - 1];
}
template<typename T>
const T& Vector<T>::back() const
{
    if (!this->empty())
        return elements[size() - 1];
}
template <typename T>
void Vector<T>::push_back(const T &s)
{
    chk_n_alloc();
    alloc.construct(first_free++, s);
}
template<typename T>
T* Vector<T>::insert(iterator b, const T &value)
{
    if (b < elements || b> first_free)    //b可以为尾后迭代器
    {
        cout << "out of memory" << endl;
        exit(0);
    }
    int num = b - elements;
    if (size() == capacity()) 
    {
        reallocate();
        b = elements + num;                         //重新分配内存后原来的指针b失效了,所以此处令b指向新分配的内存中
    }
    for (iterator p = first_free; p > b; p--)
        *p = *(p - 1);
    *b = value;
    first_free++;
    return b;
}
template<typename T>
T* Vector<T>::erase(iterator b)
{
    if (b < elements || b >= first_free)  //确保迭代器在范围内,否则未定义,b不能为尾后迭代器
    {
        cout << "out of memory" << endl;
        exit(0);
    }
    iterator q = b + 1;
    int num = q - elements;
    iterator p = first_free - 1;
    for (; b < p; b++)
        *b = *(b + 1);
    first_free--;
    if (size() <= capacity() / 4)  //防止删除后空闲空间太大,浪费空间
    {
        reallocate();
        iterator q1 = elements + num;            //重新进行内存分配后原来的指针q可能失效了
        return q1;
    }
    return q;
}
template<typename T>
void Vector<T>::clear()
{
    while(elements != first_free)
        alloc.destroy(--first_free);
}

#endif

2 测试代码(和之前一样)

#include <string>
#include"Vector.h"     //注意当这里不是标准库的头文件,是自己写的,要用双引号,整了好久,还以为程序出错了。。
using namespace std;
int main()
{
    // 利用构造函数
    Vector<int> v1;
    Vector<int> v2(5, 9);
    Vector<int> v3(v2);
    Vector<int> v4(v2.begin(), v2.end());
    if (v1.empty())
        cout << "v1为空,大小为:" << v1.size() << endl;
    cout << "向v1插入元素:";
    int a;
    while (cin >> a)
        v1.push_back(a);
    if (!v1.empty())
        cout << "v1不为空,大小为:" << v1.size() << "容量为:" << v1.capacity() << endl;
    cout << "元素为:";
    for (Vector<int>::iterator iter = v1.begin(); iter != v1.end(); ++iter)
        cout << *iter << "   ";
    cout << endl;
    cout << "重新插入后:";
    v1.insert(v1.begin() + 1, 4);
    cout << "此时v1大小为:" << v1.size() << "容量为:" << v1.capacity() << endl;
    cout << "元素为:";
    for (Vector<int>::iterator iter = v1.begin(); iter != v1.end(); ++iter)
        cout << *iter << "   ";
    cout << endl;
    cout << "删除元素后为:";
    v1.pop_back();
    for (Vector<int>::iterator iter = v1.begin(); iter != v1.end(); ++iter)
        cout << *iter << "   ";
    cout << endl;
    cout << "再次删除元素后为:";
    v1.erase(v1.begin() + 2);
    for (Vector<int>::iterator iter = v1.begin(); iter != v1.end(); ++iter)
        cout << *iter << "   ";
    cout << endl;
    cout << "v2元素为:";
    for (Vector<int>::iterator iter = v2.begin(); iter != v2.end(); ++iter)
        cout << *iter << "   ";
    cout << endl;
    cout << "v3元素为:";
    for (Vector<int>::iterator iter = v3.begin(); iter != v3.end(); ++iter)
        cout << *iter << "   ";
    cout << endl;
    cout << "v4元素为:";
    for (Vector<int>::iterator iter = v4.begin(); iter != v4.end(); ++iter)
        cout << *iter << "   ";
    cout << endl;
    if (v1 == v3)
        cout << "v1与v3相等";
    else
        cout << "v1与v3不相等" << endl;
    Vector<int> v = { 1, 2, 3, 4, 5 };
    Vector<int> v5;
    v5 = v;
    cout << "v5元素为:";
    for (Vector<int>::iterator iter = v5.begin(); iter != v5.end(); ++iter)
        cout << *iter << "   ";
    cout << endl;
    v5.push_back(99);

    v5.resize(2, 2);
    cout << "操作后v5元素为:";
    for (Vector<int>::iterator iter = v5.begin(); iter != v5.end(); ++iter)
        cout << *iter << "   ";
    cout << endl;
    std::cout << v5.capacity() << "\n";
    return 0;
}

3 运行结果:

 

posted on 2017-05-27 09:44  liuamin  阅读(987)  评论(1编辑  收藏  举报