• 5 线性表的顺序存储结构:顺序表


    1 线性表(List)

    • 线性表(List)是具有相同类型的 n(n ≥ 0)个数据元素的有限序列

    • 线性表的表现形式

      • 0 个或多个数据元素组成的集合
      • 数据元素在位置上是有序排列的
      • 数据元素的个数是有限的
      • 数据元素的类型必须相同
    • 线性表的常用操作

      • 将元素插入线性表
      • 将元素从线性表中删除
      • 获取目标位置处元素的值
      • 设置目标位置处元素的值
      • 获取线性表的长度
      • 清空线性表

    2 线性表抽象类:List

    • 线性表在 C++ 中表现为一个抽象类,用来被继承

    • List 抽象类实现

      //List.h
      template <typename T>
      class List : public Object
      {
      public:
          virtual bool insert(int i,const T& e) = 0;
          virtual bool remove(int i) = 0;
          virtual bool set(int i,const T& e) = 0;
          virtual bool get(int i,T& e) const = 0;
          virtual int length() const = 0;
          virtual void clear() = 0;
      };
      

    3 线性表的顺序存储结构:SeqList

    • 线性表的顺序存储结构(SeqList,指的是用一段地址连续的存储单元依次存储线性表中的数据元素

    • SeqList 是一个抽象类

    • 设计思路:用一维数组实现顺序存储结构

      • 存储空间:T* m_array;
      • 当前长度:int m_length;
      template <typename T>
      class SeqList : public List<T>
      {
      protected:
          T* m_array;
          int m_length;
          //////
      };
      
    • 顺序存储结构的元素获取操作

      • 判断目标位置是否合法
      • 将目标位置作为数组下标获取元素
      bool SeqList<T>::get(int i,T& e) const
      {
          bool ret = ((0 <= i) && (i < m_length));
          
          if(ret)
          {
              e = m_array[i];
          }
          
          return ret;
      }
      
    • 顺序存储结构的元素插入操作

      • 判断目标位置是否合法
      • 将目标位置之后的与所有元素后移一个位置
      • 将新元素插入目标位置
      • 线性表长度加 1
      bool SeqList<T>::inert(int i,const T& e)
      {
          //i可以是最后一个元素的下一个位置:i <= m_length
          bool ret = ((0 <= i) && (i <= m_length));
          
          ret = ret && ((m_length + 1) <= capacity());
          
          if(ret)
          {
              //将要移动的元素从后往前依次往后移动一个位置
              for(int p = m_length - 1; p >= i; p--)
              {
                  m_array[p+1] = m_array[p];
              }
              m_array[i] = e;
              m_length++;
          }
          
          return ret;
      }
      
    • 顺序存储结构的元素删除操作

      • 判断目标位置是否合法
      • 将目标位置后的所有元素前移一个位置
      • 线性表长度减 1
      bool SeqList<T>::remove(int i)
      {
          bool ret = ((0 <= i) && (i < m_length));
          
          if(ret){
              //将要移动的元素从前往后依次往前移动一个位置
              for(int p = i; p < m_length - 1; p++){
                  m_array[p] = m_array[p+1];
              }
              m_length--;
          }
          
          return ret;
      }
      

    4 顺序存储结构(SeqList)的抽象实现

    • 顺序存储结构线性表的抽象实现:实现 SeqList 抽象类

    • SeqList 类设计要点

      • 抽象类模板,存储空间的位置和大小由子类(StaticListDynamicList)完成,不能生成具体的对象
      • 实现顺序存储结构线性表的关键操作(增,删,查等)
      • 提供数组操作符,方便快速获取元素
    • SeqList.h

      #include "Exception.h"
      
      namespace DTLib
      {
      
      template <typename T>
      class SeqList : public List<T>
      {
      protected:
          T* m_array;  //顺序存储空间
          int m_length;  //当前线性表长度
      public:
          bool insert(int i,const T& e){
              bool ret = ((0 <= i) && (i <= m_length));
              //这一步的判断很必要
              ret = ret && ((m_length + 1) <= capacity());
      
              if(ret)
              {
                  for(int p = m_length - 1; p >= i; p--)
                  {
                      m_array[p+1] = m_array[p];
                  }
                  m_array[i] = e;
                  m_length++;
              }
      
              return ret;
          }
      
          bool remove(int i)
          {
              bool ret = ((0 <= i) && (i < m_length));
      
              if(ret)
              {
                  for(int p = i; p < m_length - 1; p++)
                  {
                      m_array[p] = m_array[p+1];
                  }
                  m_length--;
              }
      
              return ret;
          }
      
          bool set(int i,const T& e)
          {
              bool ret = ((0 <= i) && (i < m_length));
      
              if(ret)
              {
                  m_array[i] = e;
              }
      
              return ret;
          }
      
          bool get(int i,T& e) const
          {
              bool ret = ((0 <= i) && (i < m_length));
              if(ret)
              {
                  e = m_array[i];
              }
              return ret;
          }
      
          int length() const
          {
              return m_length;
          }
      
          void clear()
          {
              m_length = 0;
          }
      
          //顺序存储线性表的数组访问方式
          //非const对象
          T& operator[] (int i)
          {
              if((0 <= i) && (i < m_length))
              {
                  return m_array[i];
              }
              //抛出越界异常
              else
              {
                 THROW_EXCEPTION(IndexOutOfBoundsException,"Parameter i is invalid ...");
              }
          }
      
          //const对象:const对象只能调用const成员函数
          T operator[] (int i) const
          {
              return (const_cast<SeqList<T>&>(*this))[i];
          }
      
          //顺序存储空间的容量
          virtual int capacity() const = 0;  //在子类中完成
      };
      
      }
      
    • 使用

      #include "SeqList.h"
      
      using namespace std;
      
      int main()
      {
          //SeqList<int> l;  //error: cannot declare variable 'l' to be of abstract type 'DTLib::SeqList<int>'
          SeqList<int>* l;  //可以声明一个指针
          return 0;
      }
      

    5 StaticList 类和 DynamicList 类

    5.1 实现 Staticlist 类

    • Staticlist 类设计要点

      • 类模板
      • 使用原生数组作为顺序存储空间
    • 使用模板参数决定数组大小

    • StaticList.h

      #include "SeqList.h"
      namespace DTLib
      {
      
      //模板参数T,N:T决定线性表元素类型,N决定线性表长度
      template <typename T,int N>
      class StaticList : public SeqList<T>
      {
      protected:
          T m_space[N];  //顺序存储空间,N为模板参数
      public:
          //构造函数:指定父类成员的具体值
          StaticList(){
              this->m_array = m_space;
              this->m_length = 0;
          }
      
          int capacity() const{
              return N;
          }
      };
      
      }
      
    • 使用

      int main()
      {
          StaticList<int,5> l;
      
          for(int i = 0; i < l.capacity(); i++){
              //每次都往线性表的头部插入
              l.insert(0,i);
          }
      
          for(int i = 0; i < l.length(); i++){
              cout << l[i] << endl;
          }
      
          l[0] *= l[0];
      
          for(int i = 0; i < l.length(); i++){
              cout << l[i] << endl;
          }
      
          try
          {
              l[5] = 5;
          }
          catch(Exception& e)
          {
              cout << e.message() << endl;
              cout << e.location() << endl;
          }
          return 0;
      }
      
      //输出结果
      4
      3
      2
      1
      0
          
      16
      3
      2
      1
      0
          
      Parameter i is invalid ...
      ..DTLibSeqList.h:78
      

    5.2 实现 DynamicList 类

    • DynamicList 类设计要点

      • 类模板
      • 申请连续堆空间作为顺序存储空间
      • 动态设置顺序存储空间的大小
      • 保证重置顺序存储空间时的异常安全性
    • 函数异常安全的概念

      • 不泄露任何资源
      • 不允许破坏数据
    • 函数异常安全的基本保证

      • 如果异常被抛出
        • 对象内的任何成员仍然能保持有效状态
        • 没有数据的破坏及资源泄露
    • DynamicList.h

      #include "SeqList.h"
      namespace DTLib
      {
      
      template <typename T>
      class DynamicList : public SeqList<T>
      {
      protected:
          int m_capcaity;  //记录顺序存储空间的大小,通过构造函数的参数来指定
      public:
          //构造函数:动态申请堆内存空间
          DynamicList(int capacity)
          {
              this->m_array = new T[capacity];
              if(this->m_array != NULL)
              {
                  this->m_length = 0;
                  this->m_capcaity = capacity;
              }
              else
              {
                  THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicList object ...");
              }
          }
      
          int capacity() const
          {
              return m_capcaity;
          }
      
          //重新设置顺序存储空间的大小:需要考虑异常安全
          void resize(int capacity)
          {
              if(capacity != m_capcaity)
              {
                  //为什么不直接操作成员变量指针m_array:防止下面的复制操作出现问题
                  T* array = new T[capacity];  // 新申请的堆空间
                  if(array != NULL)
                  {
                      int length = this->m_length < capacity ? this->m_length : capacity;  // 判断需要复制的数据元素个数
                      //进行复制数据元素操作
                      for(int i=0;i<length;i++)
                      {
                          array[i] = this->m_array[i];
                      }
                      
                      T* temp = this->m_array;  // 利用temp指向重置前的存储空间
      
                      this->m_array = array;
                      this->m_length = length;
                      this->m_capcaity = capacity;
                      
                      delete[] temp;  // 此处才释放重置前的存储空间,防止之前释放发生异常抛出
      
                  }
                  else
                  {
                      THROW_EXCEPTION(NoEnoughMemoryException,"No memory to resize DynamicList object ...");
                  }
              }
          }
      
          //析构函数:归还空间
          ~DynamicList()
          {
              delete[] this->m_array;
          }
      };
          
      }
      
    • 使用

      int main()
      {
          DynamicList<int> l(5);
      
          for(int i = 0; i < l.capacity(); i++){
                  l.insert(0,i);
              }
      
          for(int i = 0; i < l.length(); i++){
              cout << l[i] << endl;
          }
      
          l[0] *= l[0];
      
          for(int i = 0; i < l.length(); i++){
              cout << l[i] << endl;
          }
      
          try{
              l[5] = 5;
          }
          catch(Exception& e){
              cout << e.message() << endl;
              cout << e.location() << endl;
      
              l.resize(10);
      
              l.insert(5,50);
          }
      
          l[5] = 5;
      
          for(int i = 0; i < l.length(); i++){
              cout << l[i] << endl;
          }
      
          l.resize(3);
      
          for(int i = 0; i < l.length(); i++){
              cout << l[i] << endl;
          }
      
          return 0;
      }
      
      //输出
      
      

    6 顺序存储线性表的分析

    6.1 时间分析

    • SeqList.h 效率分析

      template <typename T>
      class SeqList: public List<T>
      {
      public:
          bool insert(int i,const T& e);  //O(n)
          bool remove(int i);  //O(n)
          bool set(int i,const T& e);  //O(1)
          bool get(int i,T& e) const;  //O(1)
          int length() const;  //O(1)
          void clear();  //O(1)
          
          T& operator[] (int i);  //O(1)
          T operator[] (int i) const;  //O(1)
          
          virtual int capacity() const = 0;
      }
      
    • 问题:长度相同的两个 SeqList插入删除操作的平均耗时是否相同?

      • 不一定相同,需要看存储的对象的类型。
      • 如都含有 5 个元素的线性表 SeqList<int> s1;SeqList<string> s2;
      • 在插入和删除操作中,for 循环的赋值操作,整型的赋值操作比字符串的赋值操作(strcpy 是一个字符一个字符赋值的)耗时要小得多

    6.2 功能分析

    • 代码分析1

      • Demo

        StaticList<int*,5> s1;
        StaticList<int*,5> s2;
        
        for(int i = 0; i < s1.capacity(); ++i){
            s1.insert(0,new int(i));
        }
        
        //赋值操作
        s2 = s1;
        
        for(int i = 0; i < s1.length(); ++i){
            delete s1[i];
            delete s2[i];
        }
        
      • 分析:对于赋值操作 s2 = s1; ,会发生情况:使得链表 s1s2 中的相对应的 5 个元素都指向同一块内存。那么在下一个 for 循环中,每一个内存空间都会被释放两次

    • 代码分析2

      • Demo

        void func()
        {
            DynamicList<int> d1(5);
            //拷贝构造
            DynamicList<int> d2 = d1;
            
            for(int i=0;i<d1.capacity();++i){
                d1.insert(i,i);
                d2.insert(i,i*i);
            }
            
            for(int i=0;i<d1.length();++i){
                cout << d1[i] << endl;
            }
        }
        
      • 分析:拷贝构造时发生了什么:构造 d1 时,m_array 会指向内存中一块空间,构造 d2 时,d2m_array 同样会指向相同的一块内存,那么在随后的 insert 操作中,后进行的 insert 操作会覆盖之前的 insert 操作,同样也会有同一块内存多次释放的问题

    • 结论:对于容器类型的类,可以考虑禁用拷贝构造和赋值操作

      线性表作为容器类,应该避免拷贝构造和拷贝赋值

      template<typename T>
      class List: public Object
      {
      protected:
          List(const List&);
          List& operator= (const List&);
      public:
          List(){}
          //...
      }
      
    • 代码优化

      • 禁用拷贝构造和赋值操作

        //List.h
        #include "Object.h"
        namespace DTLib
        {
        template <typename T>
        class List : public Object
        {
        protected:
            //禁用
            List(const List&);
            List& operator= (const List&);
        public:
            List() { } //这里在添加了拷贝构造函数后,需要手动添加一个默认构造函数
            virtual bool insert(int i,const T& e) = 0;
            virtual bool remove(int i) = 0;
            virtual bool set(int i,const T& e) = 0;
            virtual bool get(int i,T& e) const = 0;
            virtual int length() const = 0;
            virtual void clear() = 0;
        };
        }
        
      • 以重载的方式添加一个默认的插入操作:往线性表尾部插入数据

        //List.h
        #ifndef LIST_H
        #define LIST_H
        
        #include "Object.h"
        namespace DTLib
        {
        template <typename T>
        class List : public Object
        {
        protected:
            List(const List&);
            List& operator= (const List&);
        public:
            List() { } //这里在添加了拷贝构造函数后,需要手动添加一个默认构造函数
            virtual bool insert(const T& e) = 0;
            virtual bool insert(int i,const T& e) = 0;
            virtual bool remove(int i) = 0;
            virtual bool set(int i,const T& e) = 0;
            virtual bool get(int i,T& e) const = 0;
            virtual int length() const = 0;
            virtual void clear() = 0;
        };
        }
        
        //SeqList.h
        #ifndef SEQLIST_H
        #define SEQLIST_H
        
        #include "Exception.h"
        
        namespace DTLib
        {
        
        template <typename T>
        class SeqList : public List<T>
        {
        protected:
            T* m_array;  //顺序存储空间
            int m_length;  //当前线性表长度
        public:
            bool insert(int i,const T& e){
                bool ret = ((0 <= i) && (i <= m_length));
                ret = ret && ((m_length + 1) <= capacity());
        
                if(ret){
                    for(int p = m_length - 1;p >= i;p--){
                        m_array[p+1] = m_array[p];
                    }
                    m_array[i] = e;
                    m_length++;
                }
        
                return ret;
            }
        
            bool insert(const T& e){
                return insert(m_length,e);
            }
        };
        }
        
    • 代码分析3

      • Demo

        int main()
        {
            StaticList<int,5> list;
            
            for(int i = 0; i < list.capacity(); ++i){
                //将线性表当作数组使用
                list[i] = i * i;  //报越界异常:Parameter i is invalid ...
                //if((0 <= i) && (i < m_length))中,i < m_length 是不满足的:m_lenght = 0
            }
            
            return 0;
        }
        
      
      
    • 问题:将线性表当作数组使用

    • 分析:线性表必须先插入元素(使用 inert,才能使用操作符[] 访问元素

      顺序存储结构线性表提供了数组操作符重载,通过重载能够快捷方便地获取目标位置处的数据元素,在具体的使用形式上类似数组 ,但是由于本质不同,不能代替数组使用

    7 数组类 Array 的创建

    • 基于顺序存储的线性表的主要问题
      • 功能上的问题:链表误当作数组来使用(重载了 [] 操作符)——利用数组类解决
      • 效率上的问题:基于顺序存储的线性表插入和删除的效率较低——利用线性表的链式存储解决

    7.1 抽象类 Array 设计

    • 需求分析

      • 创建数组类代替原生数组的使用
      • 数组类包含长度信息
      • 数组类能够主动发现越界访问,例如上一节的代码分析3,数组发生越界却没有报告异常
    • Array 设计要点

      • 抽象模板类,存储空间的位置和大小由子类完成
      • 重载数组操作符,判断访问下标是否合法
      • 提供数组长度的抽象访问函数
      • 提供数组对象间的复制操作
    • Array 类的声明

      template <typename T>
      class Array: public Object
      {
      protected:
          T* m_array;
      public:
          virtual bool set(int i,const T& e);
          virtual bool get(int i,T& e) const;
          virtual int length() const = 0;
          //数组访问操作符
          T& operator[] (int i);
          T operator[] (int i) const;
      }
      
    • 数组抽象类的实现

      //Array.h
      #include "Object.h"
      #include "Exception.h"
      
      namespace DTLib
      {
      template <typename T>
      class Array : public Object
      {
      protected:
          T* m_array;
      public:
          virtual bool set(int i,const T& e){  //O(1)
              bool ret = ((0 <= i) && (i < length()));
      
              if(ret){
                  m_array[i] = e;
              }
              return ret;
          }
      
          virtual bool get(int i,T& e) const{  //O(1)
              bool ret = ((0 <= i) && (i < length()));
      
              if(ret){
                  e = m_array[i];
              }
              return ret;
          }
      
          //数组访问操作符
          T& operator[] (int i){  //O(1)
              if((0 <= i) && (i < length())){
                  return m_array[i];
              }
              else{
                  THROW_EXCEPTION(IndexOutOfBoundsException,"Parameter i is invalid ...");
              }
          }
      
          T operator[] (int i) const{  //O(1)
              return (const_cast<Array<T>&>(*this)[i]);
          }
      
          virtual int length() const = 0;
      };
      }
      

    7.2 子类 StaticArray 类设计

    • StaticArray 类设计要点

      • 类模板
      • 封装原生数组
      • 使用模板参数决定数组大小
      • 实现函数返回数组长度
      • 拷贝构造和赋值操作
    • StaticArray 类的声明

      template <typename T,int N>
      class StaticArray : public Array<T>
      {
      protected:
          T m_space[N];
      public:
          StaticArray();
          //拷贝和赋值操作
          StaticArray(const StaticArray<T,N>& obj);
          StaticArray<T,N>& operator= (const StaticArray<T,N>& obj);
          
          int length() const;
      };
      
    • 静态数组类的实现

      //StaticArray.h
      #include "Array.h"
      
      namespace DTLib
      {
      
      template <typename T,int N>
      class StaticArray : public Array<T>
      {
      protected:
          T m_space[N];
      public:
          StaticArray(){  //O(1)
              this->m_array = m_space;
          }
      
          //拷贝和赋值操作
          StaticArray(const StaticArray<T,N>& obj){  //O(n)
              this->m_array = m_space;
              for(int i=0;i<N;++i){
                  m_space[i] = obj.m_space[i];
              }
          }
      
          StaticArray<T,N>& operator= (const StaticArray<T,N>& obj){  //O(n)
              //判断是否自赋值
              if(this != &obj){
                  for(int i=0;i<N;++i){
                      m_space[i] = obj.m_space[i];
                  }
              }
      
              return *this;
          }
      
          int length() const{  //O(1)
              return N;
          }
      };
      
      }
      
    • 使用

      #include "StaticArray.h"
      
      using namespace std;
      using namespace DTLib;
      
      
      int main()
      {
          StaticArray<int,5> s1;
      
          for(int i=0;i<s1.length();++i){
              s1[i] = i * i;
          }
      
          for(int i=0;i<s1.length();++i){
              cout << s1[i] << endl;
          }
      
          StaticArray<int,5> s2;
          //支持数组的相互赋值
          s2 = s1;
      
          for(int i=0;i<s2.length();++i){
              cout << s2[i] << endl;
          }
      
          s1[6] = 100;  //Array类会抛出异常 : 'DTLib::IndexOutOfBoundsException'
          
          int s3[5];  //原生数组
          s3[6] = 100;  //越界,但不报异常
      
          return 0;
      }
      

    7.3 子类 DynamicArray 类设计

    • DynamicArray 类设计要点

      • 类模板
      • 动态确定内部数组空间的大小
      • 实现函数返回数组长度
      • 拷贝构造和赋值操作
    • DynamicArray 类的声明

      template <typename T>
      class DynamicArray : public Array<T>
      {
      protected:
          int m_length;
      public:
          DynamicArray(int length);
          
          DynamicArray(const DynamicArray<T>& obj);
          DynamicArray<T>& operator= (const DynamicArray<T>& obj);
          
          int length() const;
          void resize(int length);  //动态重置数组的长度
          
          ~DynamicArray();
      };
      
    • 动态数组类的实现

      //DynamicArray.h
      #include "Array.h"
      #include "Exception.h"
      
      namespace DTLib
      {
      
      template <typename T>
      class DynamicArray : public Array<T>
      {
      protected:
          int m_length;
      public:
          DynamicArray(int length){
              this->m_array = new T[length];
      
              if(this->m_array != NULL){
                  this->m_length = length;
              }
              else{
                  THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicArray object ...");
              }
          }
      
          DynamicArray(const DynamicArray<T>& obj){
              this->m_array = new T[obj.m_length];
      
              if(this->m_array != NULL){
                  this->m_length = obj.length;
      
                  for(int i=0;i<obj.m_length;++i){
                      this->m_array[i] = obj.m_array[i];
                  }
               }
              else{
                  THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicArray object ...");
              }
          }
      
          DynamicArray<T>& operator= (const DynamicArray<T>& obj){
              if(this != &obj){
                  T* array = new T[obj.m_length];
      
                  if(array != NULL){
                      for(int i=0;i<obj.m_length;++i){
                          array[i] = obj.m_array[i];
                      }
      
                      T* temp = this->m_array;
      
                      this->m_array = array;
                      this->m_length = obj.m_length;
      
                      delete[] temp;
                  }
                  else{
                      THROW_EXCEPTION(NoEnoughMemoryException,"No memory to copy object ...");
                  }
              }
      
              return *this;
          }
      
          int length() const{
              return m_length;
          }
      
          //动态重置数组的长度
          void resize(int length){
              if(length != m_length){
                  T* array = new T[length];
      
                  if(array != NULL){
                      int size = (length < m_length) ? length : m_length;
      
                      for(int i=0;i<size;++i){
                          array[i] = this->m_array[i];
                      }
      
                      T* temp = this->m_array;
      
                      this->m_array = array;
                      this->m_length = length;
      
                      delete[] temp;
                  }
                  else {
                      THROW_EXCEPTION(NoEnoughMemoryException,"No memory to resize object ...");
                  }
              }
          }
      
          ~DynamicArray(){
              delete[] this->m_array;
          }
      };
      
      }
      
    • 使用

      #include "DynamicArray.h"
      
      using namespace std;
      using namespace DTLib;
      
      
      int main()
      {
          DynamicArray<int> s1(5);
      
          for(int i=0;i<s1.length();++i){
              s1[i] = i * i;
          }
      
          for(int i=0;i<s1.length();++i){
              cout << s1[i] << endl;
          }
      
          DynamicArray<int> s2(10);
      
          s2 = s1;
          s2.resize(8);
          for(int i=0;i<s2.length();++i){
              cout << s2[i] << endl;
          }
          
          s2.resize(3);
          for(int i=0;i<s2.length();++i){
              cout << s2[i] << endl;
          }
          
          s2[4] = 100;
      
          return 0;
      }
      
    • DynamicArray 类中的函数实现存在重复的逻辑,进行代码优化

      • init :对象构造时的初始化操作
      • copy :在堆空间中申请新的内存,并执行拷贝操作
      • update :将指定的堆空间作为内部存储数组使用
      //DynamicArray.h
      #include "Array.h"
      #include "Exception.h"
      
      namespace DTLib
      {
      
      template <typename T>
      class DynamicArray : public Array<T>
      {
      protected:
        int m_length;
        //在堆空间中申请一个新的数组ret,大小为newLen,再将传入的array数组中的元素拷贝到新的数组中
        T* copy(T* array,int len,int newLen){
            T* ret = new T[newLen];
      
            if(ret != NULL){
                //数据元素的拷贝
                int size = (len < newLen) ? len : newLen;
      
                for(int i=0;i<size;++i){
                    ret[i] = array[i];
                }
            }
      
            return ret;
        }
      
        void update(T* array,int length){
            if(array != NULL){
                //异常安全
                T* temp = this->m_array;
      
                this->m_array = array;
                this->m_length = length;
      
                delete[] temp;
            }
            else{
                THROW_EXCEPTION(NoEnoughMemoryException,"No memory to update DynamicArray object ...");
            }
        }
      
        void init(T* array,int length){
            if(array != NULL){
                this->m_array = array;
                this->m_length = length;
            }
            else{
                THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicArray object ...");
            }
        }
      
      public:
        DynamicArray(int length){
            init(new T[length],length);
        }
      
        DynamicArray(const DynamicArray<T>& obj){
            T* array = copy(obj.m_array,obj.m_length,obj.m_length);
            init(array,obj.m_length);
        }
      
        DynamicArray<T>& operator= (const DynamicArray<T>& obj){
            if(this != &obj){
                T* array = copy(obj.m_array,obj.m_length,obj.m_length);
                update(array,obj.m_length);
            }
            return *this;
        }
      
        int length() const{
            return m_length;
        }
      
        //动态重置数组的长度
        void resize(int length){
            if(length != m_length){
                T* array = copy(this->m_array,m_length,length);
                update(array,length);
            }
        }
      
        ~DynamicArray(){
            delete[] this->m_array;
        }
      };
      
      }
      
  • 相关阅读:
    IO操作之BIO、NIO、AIO
    IO之Socket网络编程
    this.getClass()和super.getClass()得到的是同一个类
    经济增长的背后
    SVN分支创建与合并
    .net类库里ListView的一个BUG
    VS2010调试技巧
    用C#代码编写的SN快速输入工具
    请教如何改善C#中socket通信机客户端程序的健壮性
    利用WebClient实现对Http协议的Post和Get对网站进行模拟登陆和浏览
  • 原文地址:https://www.cnblogs.com/bky-hbq/p/13821369.html
Copyright © 2020-2023  润新知