zoukankan      html  css  js  c++  java
  • Vector模板类的建立与实现(二)

    之前用数组简单实现了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() << "
    ";
        return 0;
    }

    3 运行结果:

  • 相关阅读:
    java泛型
    跨域传递
    laravel的一些语法
    去重
    laravel的一些查询语句
    mysql把之前表单进行拆分
    Laravel5.1接收json数据
    thinkphp5 composer安装验证码
    关于地图经纬度的问题
    tp5分组查询
  • 原文地址:https://www.cnblogs.com/liuamin/p/6911540.html
Copyright © 2011-2022 走看看