zoukankan      html  css  js  c++  java
  • 实现Vector<T>(代码)

    #pragma once
    //迭代器模板  可以使用类模板
    #include <exception>
    #include <string>
    using namespace std;
    
    template<typename T>
    class MyVector
    {
    public:
        /** 迭代器 **/
        class Iterator
        {
            friend class MyVector;
        public:
            Iterator(T* pos) :m_pos(pos)
            {
            }
            Iterator& operator++() //前++
            {
                ++m_pos;
                return *this;
            }
            Iterator operator++(int) //后++
            {
                int* posOld = m_pos;
                ++m_pos;
                return Iterator(posOld);
            }
            Iterator& operator--()//前--
            {
                --m_pos;
                return *this;
            }
            Iterator operator--(int)
            {
                int* posOld = m_pos;
                --m_pos;
                return Iterator(posOld);
            }
            bool operator==(Iterator& itr)
            {
                return (m_pos == itr.m_pos);
            }
            bool operator!=(Iterator& itr)
            {
                return !(*this == itr);
            }
            T& operator*()
            {
                return *m_pos;
            }
            T* operator->()
            {
                return m_pos;
            }
        private:
            T* m_pos = nullptr; //元素位置
        };
    
    public:
        Iterator begin(); //返回指向第一个元素的迭代器
        Iterator end();//返回指向最后一个元素后面位置的迭代器
    
    public:
        MyVector();
        ~MyVector();
        MyVector(const MyVector& obj);
    
    public:
        MyVector& operator=(const MyVector& obj);
    
    public:
        /**增加**/
        void push_back(const T& nVal);
    
        /*
        * 其他:会抛出异常exception
        */
        Iterator intsert(Iterator itr, const T& nVal);
    
        /* 修改 */
        T& operator[](int nIdx);
        T& at(int nIdx);
    
        /* 删除 */
        bool erase(Iterator itr);
        void pop_back();
    
    
        /* 查询 */
        Iterator find(const T& nVal);
    
    
        /* 其它 */
        int size();
    
    private:
        void CheckCapacity(); //检查内存是否足够放入新的数据
    
    private:
        T*   m_pData = nullptr; //保存数组元素的缓冲区
        int  m_nCapacity = 0;   //整块内存的大小
        int  m_nSize = 0;       //当前内存中有多少数据
    
    private:
        const int m_nInitialCapacityLen = 8; //初始化内存的大小
    };
    
    //构造 初始化
    template<typename T>
    MyVector<T>::MyVector()
    {
        m_pData = new T[m_nInitialCapacityLen];
        m_nCapacity = m_nInitialCapacityLen;
        m_nSize = 0;
    }
    
    
    template<typename T>
    MyVector<T>::~MyVector()
    {
        /*
        * 释放资源
        */
        if (m_pData != nullptr)
        {
            delete[] m_pData;
            m_pData = nullptr;
        }
    
        m_nSize = 0;
        m_nCapacity = 0;
    }
    
    //返回指向第一个元素的迭代器
    template<typename T>
    typename MyVector<T>::Iterator MyVector<T>::begin()
    {
        //数据首地址给m_pos
        return Iterator(m_pData);
    }
    
    //返回指向最后一个元素后面位置的迭代器
    template<typename T>
    typename MyVector<T>::Iterator MyVector<T>::end()
    {
        //返回地址为数据末尾最后一个元素位置加一  没有存入新的地址的地方
        return Iterator(m_pData + m_nSize);
    }
    
    template<typename T>
    MyVector<T>::MyVector(const MyVector& obj)
    {
        //拷贝构造函数  这里是浅拷贝
        *this = obj;
    }
    
    //等号运算符重载,因为是浅拷贝,所以拷贝构造的时候不能用memcpy;否则类模板释放同一个指针 堆地址重复释放系统会崩
    template<typename T>
    MyVector<T>& MyVector<T>::operator=(const MyVector& obj)
    {
        int i;
        //释放自己
        if (m_pData != nullptr)
        {
            delete[] m_pData;
        }
    
        //申请新内存
        m_pData = new T[obj.m_nCapacity];
        for (i = 0; i < obj.m_nSize; i++)
        {
            m_pData[i] = obj.m_pData[i];
        }
    
        m_nSize = obj.m_nSize;
        m_nCapacity = obj.m_nCapacity;
    
        return *this;
    }
    
    /*
    增加
    */
    template<typename T>
    void MyVector<T>::push_back(const T& nVal)
    {
        //检查内存大小
        CheckCapacity();
    
        //存入新的数值
        m_pData[m_nSize] = nVal;
        m_nSize++;
    }
    
    template<typename T>
    typename MyVector<T>::Iterator MyVector<T>::intsert(Iterator itr, const T& nVal)
    {
        /*
        *  获取索引值
        */
        T* pos = itr.m_pos;
        int nIdx = pos - m_pData;
    
    
        /*
        * 检查索引是否越界
        */
        if (nIdx < 0 || nIdx > m_nSize)
        {
            throw exception("索引越界");
        }
    
        /*
        * 检查内存大小
        */
        CheckCapacity();
    
        /*
        * 拷贝数据
        */
        int nSizeOfCopyData = (m_nSize - nIdx)*sizeof(T);   //拷贝的数据的大小
        T* pBeginPos = m_pData + nIdx;        //拷贝数据的起始位置
        T* pEndPos = m_pData + nIdx + 1;   //拷贝数据的目的位置
        memcpy(pEndPos, pBeginPos, nSizeOfCopyData);
    
        /*
        *  保存新的数据
        */
        m_pData[nIdx] = nVal;
        m_nSize++;
    
        return Iterator(&m_pData[nIdx]);
    }
    
    /*
    修改
    */
    template<typename T>
    T& MyVector<T>::operator[](int nIdx)
    {
        /*
        * 检查索引是否越界
        */
        if (nIdx < 0 || nIdx >= m_nSize)
        {
            throw exception("索引越界");
        }
    
        return m_pData[nIdx];
    }
    template<typename T>
    T& MyVector<T>::at(int nIdx)
    {
        /*
        * 检查索引是否越界
        */
        if (nIdx < 0 || nIdx >= m_nSize)
        {
            throw exception("索引越界");
        }
    
    
        return m_pData[nIdx];
    }
    
    /*
    删除
    */
    template<typename T>
    bool MyVector<T>::erase(Iterator itr)
    {
        /*
        *  获取索引值
        */
        T* pos = itr.m_pos;
        int nIdx = pos - m_pData;
    
        /*
        * 检查索引是否越界
        */
        if (nIdx < 0 || nIdx >= m_nSize)
        {
            throw exception("索引越界");
        }
    
        /*
        * 拷贝数据,覆盖被删除的数据
        */
        T* pBeginPos = m_pData + nIdx + 1; //获取拷贝数据的起始位置
        T* pEndPos = m_pData + nIdx;       //获取拷贝数据的目标位置
        int  nSizeOfCopyData = (m_nSize - nIdx - 1)*sizeof(T); //拷贝的数据大小
        memcpy(pEndPos, pBeginPos, nSizeOfCopyData);
    
        m_nSize--;
        return true;
    }
    template<typename T>
    void MyVector<T>::pop_back()
    {
        /*
        * 检查索引是否越界
        */
        if (m_nSize <= 0)
        {
            throw exception("索引越界");
        }
    
        //删除数据
        m_nSize--;
    }
    
    /*
    查询
    */
    template<typename T>
    typename MyVector<T>::Iterator MyVector<T>::find(const T& nVal)
    {
        for (int i = 0; i < m_nSize; i++)
        {
            if (nVal == m_pData[i])
            {
                return Iterator(&m_pData[i]);
            }
        }
    
        return Iterator(nullptr);
    }
    
    /*
    其它
    */
    template<typename T>
    int MyVector<T>::size()
    {
        return m_nSize;
    }
    
    //检查内存是否足够放入新的数据
    template<typename T>
    void MyVector<T>::CheckCapacity()
    {
        //内存不够,申请新内存
        if (m_nSize >= m_nCapacity)
        {
            T* pData = new T[m_nCapacity * 2];              //申请新内存
            memcpy(pData, m_pData, m_nCapacity * sizeof(T));  //拷贝原来的数据
            delete[] m_pData;   //释放原来的额内存
            m_pData = pData;
            m_nCapacity = m_nCapacity * 2;
        }
    }
    学如逆水行舟,不进则退。 博客园技术交流群 群 号:1073255314 (本群没人,刚刚建立 -_-!!! )
  • 相关阅读:
    lab anycast rp
    激光 & 激光器
    管道机器人结构设计及控制系统搭建
    自动开关灯装置
    基于MATLAB步态算法仿真的六足仿生机器人
    蓝牙AT模式
    语音识别LD3320
    蓝牙模块设置
    6红外遥控程序
    62、如何消除碎片文件
  • 原文地址:https://www.cnblogs.com/Mj-NaijAm/p/13611600.html
Copyright © 2011-2022 走看看