外观
03.线性表的本质和操作、顺序存储结构的抽象实现、顺序存储线性表的分析、数组类的创建
约 5315 字大约 18 分钟
数据结构线性表顺序存储结构顺序存储线性表
2022-06-25
十四、线性表的本质和操作
1、生活中的智慧
幼儿园老师总会让小朋友以同样的排队秩序出行。
2、线性表(List)的表现形式
零个或多个数据元素组成的集合
数据元素在位置上是有序排列的
数据元素的个数是有限的
数据元素的类型必须相同
3、线性表(List)的抽象定义

4、线性表(List)的性质

5、思考题
下面的关系中可以用线性表描述的是
班级中同学的友谊关系 (X一对多)
公司中的上下级关系 (X一对多)
冬天图书馆用物品排队占座 (X数据类型不同)

6、问题
线性表只是一个单纯的概念吗?如何在程序中描述和使用一个线性表?
7、线性表的一些常用操作
- 将元素插入线性表
- 将元素从线性表中删除
- 获取目标位置处元素的值
- 设置目标位置处元素的值
- 获取线性表的长度
- 清空线性表
8、线性表在程序中表现为一种特殊的数据类型

9、编程实验:线性表抽象类的创建
List.h
#ifndef LIST_H_
#define LIST_H_
/***
* Include Files *
***/
#include "Object.h"
/***
* Type Definition *
***/
namespace DTLib
{
template < typename T >
class List : public Object
{
protected:
List(const List<T>&); // 拷贝构造函数 对于容器类型的类,可以考虑禁用拷贝构造和赋值操作。
List<T>& operator= (const List<T>&); // 赋值操作符重载函数 对于容器类型的类,可以考虑禁用拷贝构造和赋值操作。
public:
List() { } // 构造函数
virtual bool insert(const T& e) = 0; // 在线性表尾部插入e
virtual bool insert(int i, const T& e) = 0; // 在i处插入e
virtual bool remove(int i) = 0; // 删除第i个元素
virtual bool set(int i, const T& e) = 0; // 设置第i个元素为e
virtual bool get(int i, T& e) const = 0; // 获取第i个元素为e
virtual int find(const T& e) const = 0; // 查找指定的元素
virtual int length() const = 0; // 返回当前有效值的数量
virtual void clear() = 0; // 清空链表
List<T>& self()
{
return *this;
}
};
}
#endif // LIST_H_10、小结
- 线性表是数据元素的有序并且有限的集合
- 线性表中的数据元素必须是类型相同的
- 线性表可用于描述排队关系的问题
- 线性表在程序中表现为一种特殊的数据类型
- 线性表在C++中表现为一个抽象类
十五、线性表的顺序存储结构
1、顺序存储的定义
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表中的数据元素。

2、设计思路
可以用一维数组来实现顺序存储结构
存储空间:T*m_array;
当前长度:int m_length;

3、顺序存储结构的元素获取操作
判断目标位置是否合法
将目标位置作为数组下标获取元素

4、编程实验:图解元素获取
通过数组下标获取元素

5、顺序存储结构的元素插入操作
判断目标位置是否合法
将目标位置之后的所有元素后移一个位置
将新元素插入目标位置
线性表长度加1
6、顺序存储结构的元素插入示例

7、编程实验:图解元素插入
线性表长度+1 ===> 会不会越界;
插入的位置是否合理(不能插入的位置前后都没数据)

8、顺序存储结构的元素删除操作
1. 判断目标位置是否合法
将目标位置后的所有元素前移一个位置
线生表长度减1
9、顺序存储结构的元素删除示例

10、编程实验:图解元素删除
删除的位置是否合理(不能删除的位置没数据)

11、实战预告
To be continued …

十六、顺序存储结构的抽象实现
1、课程目标
完成顺序存储结构线性表的抽象实现

2、SeqList设计要点
抽象类模板,存储空间的位置和大小由子类完成
实现顺序存储结构线性表的关键操作(增,删,查,等)
提供数组操作符,方便快速获取元素

3、编程实验:顺序存储线性表
SeqList.h
#ifndef SEQLIST_H_
#define SEQLIST_H_
/***
* Include Files *
***/
#include "List.h"
#include "Exception.h"
/***
* Type Definition *
***/
namespace DTLib
{
template < typename T >
class SeqList : public List<T>
{
protected:
T* m_array; // 数组地址
int m_length; // 当前线性表长度
public:
/**
* Function: insert()
* Description: 在i位置,插入e
* Input: i 待插入的位置
* e 待插入的数据
* Output:
* Return: bool 是否插入成功
* Others: O(n+5) => O(n)
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
bool insert(int i, const T& e)
{
bool ret = ((0 <= i) && (i <= m_length)); // i的合法性 (不能插入的位置前后都没数据)
ret = ret && (m_length < 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++; // 线性表长度+1
}
return ret;
}
/**
* Function: insert()
* Description: 在线性表尾部,插入e
* Input: e 待插入的数据
* Output:
* Return: bool 是否插入成功
* Others: O(n)
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
bool insert(const T& e)
{
return insert(m_length, e);
}
/**
* Function: remove()
* Description: 删除i位置的元素
* Input: i 待删除的位置
* Output:
* Return: bool 是否删除成功
* Others: O(n)
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
bool remove(int i)
{
bool ret = ((0 <= i) && (i < m_length)); // i的合法性
if( ret )
{
for(int p=i; p<m_length-1; p++) // 将目标位置后的所有元素前移一个位置
{
m_array[p] = m_array[p+1];
}
m_length--; // 线性表长度-1
}
return ret;
}
/**
* Function: set()
* Description: 更新i位置的元素
* Input: i 待更新的位置
* e 待更新的数据
* Output:
* Return: bool 是否更新成功
* Others:
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
bool set(int i, const T& e)
{
bool ret = ((0 <= i) && (i < m_length)); // i的合法性
if( ret )
{
m_array[i] = e; // 更新数据
}
return ret;
}
/**
* Function: get()
* Description: 获取i位置的元素
* Input: i 待获取的位置
* Output: e 获取的元素
* Return: bool 是否获取成功
* Others: O(n)
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
bool get(int i, T& e) const
{
bool ret = ((0 <= i) && (i < m_length)); // i的合法性
if( ret )
{
e = m_array[i]; // 获取数据
}
return ret;
}
/**
* Function: find()
* Description: 查找指定的元素
* Input: i 待寻找的元素
* Output:
* Return: int 元素的位置
* Others: O(n)
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
int find(const T& e) const
{
int ret = -1;
for(int i=0; i<m_length; i++) // 遍历寻找
{
if( m_array[i] == e )
{
ret = i;
break;
}
}
return ret;
}
/**
* Function: length()
* Description: 返回当前线性表的所用数量
* Input:
* Output:
* Return: int 当前线性表的所用数量
* Others:
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
int length() const
{
return m_length;
}
/**
* Function: clear()
* Description: 清空链表
* Input:
* Output:
* Return:
* Others:
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
void clear()
{
m_length = 0;
}
/**
* Function: operator[]()
* Description: []操作符重构函数
* Input: i 待返回的元素位置
* Output:
* Return: T 元素的值
* Others: 数组访问方式
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
T& operator[] (int i)
{
if( (0 <= i) && (i < m_length) ) // i的合法性
{
return m_array[i];
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ...");
}
}
/**
* Function: operator[]()
* Description: []操作符重构函数(const类型的对象使用)
* Input: i 待返回的元素位置
* Output:
* Return: T 元素的值
* Others: 该函数调用了上一个[]操作符重构函数
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
T operator[] (int i) const
{
return (const_cast<SeqList<T>&>(*this))[i];
}
/**
* Function: capacity()
* Description: 顺序存储空间的容量
* Input:
* Output:
* Return: int 顺序存储空间的容量
* Others: 纯虚函数
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
virtual int capacity() const = 0;
};
}
#endif // SEQLIST_H_4、To be continued ...

十七、StaticList 和 DynamicList
1、课程目标
- 完成StaticList类的具体实现
- 完成DynamicList类的具体实现

2、StaticList 设计要点
- 类模板
- 使用原生数组作为顺序存储空间
- 使用模板参数决定数组大小
· 
3、编程实验:StaticList的实现
StaticList.h
#ifndef STATICLIST_H_
#define STATICLIST_H_
/***
* Include _Files *
***/
#include "SeqList.h"
/***
* Type Definition *
***/
namespace DTLib
{
template < typename T, int N >
class StaticList : public SeqList<T>
{
protected:
T m_space[N]; // 元素总数量
public:
StaticList() // 构造函数 - 指定父类成员的具体值
{
this->m_array = m_space; // 初始化元素总数量
this->m_length = 0; // 初始化当前线性表长度
}
int capacity() const // 获取元素总数量
{
return N;
}
};
}
#endif // STATICLIST_H_4、DynamicList设计要点
类模板
申请连续堆空间作为顺序存储空间
动态设置顺序存储空间的大小
保证重置顺序存储空间时的异常安全性
函数异常安全的概念
不泄漏任何资源
不允许破坏数据
函数异常安全的基本保证
如果异常被抛出
对象内的任何成员仍然能保持有效状态
没有数据的破坏及资源泄漏

5、编程实验:DynamicList的实现
DynamicList.h
#ifndef DYNAMICLIST_H_
#define DYNAMICLIST_H_
/***
* Include _Files *
***/
#include "SeqList.h"
#include "Exception.h"
/***
* Type Definition *
***/
namespace DTLib
{
template < typename T >
class DynamicList : public SeqList<T>
{
protected:
int m_capacity; // 元素总数量
public:
/**
* Function: DynamicList()
* Description: 构造函数
* Table Accessed:
* Table Updated:
* Input: capacity 元素总数量
* Output:
* Return:
* Others:
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
DynamicList(int capacity) // 构造函数 - 申请空间
{
this->m_array = new T[capacity]; // 申请堆空间
if( this->m_array != NULL )
{
this->m_length = 0; // 初始化当前线性表长度
this->m_capacity = capacity; // 初始化元素总数量
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create DynamicList object ...");
}
}
/**
* Function: capacity()
* Description: 返回元素总数量
* Table Accessed:
* Table Updated:
* Input:
* Output:
* Return: int 返回 元素总数量
* Others:
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
int capacity() const
{
return m_capacity;
}
/**
* Function: resize()
* Description: 重新设置元素数量
* Table Accessed:
* Table Updated:
* Input: capacity 新元素总数量
* Output:
* Return:
* Others:
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
void resize(int capacity)
{
if( capacity != m_capacity )
{
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++) // 将length个元素复制到新申请的堆空间中
{
array[i] = this->m_array[i]; /* 此可能发生异常,动态链表依然可用,但是会发生内存泄漏。且无法避免。*/
} /* T是一个泛型类型,赋值操作符可能被重载,并且重载的实现出现的异常,上层修改即可*/
T* temp = this->m_array; /* 此处不直接释放堆空间,防止此处抛出异常,保障动态链表异常安全性 */
this->m_array = array; // 更新 顺序存储空间
this->m_length = length; // 更新 当前线性表长度
this->m_capacity = capacity; // 更新 返回元素总数量
delete[] temp; // 删除原来的堆空间
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memory to resize DynamicList object ...");
}
}
}
/**
* Function: ~DynamicList()
* Description: 析构函数
* Table Accessed:
* Table Updated:
* Input:
* Output:
* Return:
* Others: 释放堆内存空间
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
~DynamicList()
{
delete[] this->m_array;
}
};
}
#endif // DYNAMICLIST_H_6、问题
是否可以将DynamicList 作为StaticList的子类实现?
7、小结
- StaticList 通过模板参数定义顺序存储空间
- DynamicList 通过动态内存申请定义顺序存储空间
- DynamicList 支持动态重置顺序存储空间的大小
- DynamicList 中的resize()函数实现需要保证异常安全
十八、顺序存储线性表的分析
1、效率分析

2、问题
长度相同的两个SeqList,插入和删除操作的平均耗时是否相同?
要具体问题具体分析。
3、编程实验:SeqList效率分析
- T为int和String时,字符串的拷贝更耗时。
- 由于数据类型的不同,赋值操作的效率和耗时不同。取决于线性表里存储的数据类型。
- 不能单纯只看时间复杂度O,只是参考指标,不是绝对指标,要根据实际情况分析。
- 基于顺序存储结构的线性表不适合使用类类型的对象作为数据元素存储。
4、下面的代码正确吗?为什么?


拷贝使得两个对象指向同一份堆空间,导致同一个堆空间被两次。
5、分析
对于容器类型的类,可以考虑禁用拷贝构造和赋值操作。

6、编程实验:代码优化
禁用拷贝构造和赋值操作。
7、下面的代码正确吗?为什么?不正确

线性表**必须先插入元素**,才能使用操作符[]访问元素。
8、问题分析
顺序存储结构线性表提供了数组操作符重载,通过重载能够快捷方便的获取目标位置处的数据元素,在具体的使用形式上类似数组,但是由于本质不同,不能代替数组使用。
9、实战预告:数组类开发

10、小结
- 顺序存储线性表的插入和删除操作存在重大效率隐患(不适合使用类类型的对象作为数据元素存储)
- 线性表作为容器类,应该避免拷贝构造和拷贝赋值
- 顺序存储线性表可能被当成数组误用
- 工程开发中可以考虑使用数组类代替原生数组使用
十九、数组类的创建(上)
1、课程目标
- 完成Array类的具体实现
- 完成StaticArray类的具体实现

2、需求分析
- 创建数组类代替原生数组的使用
- 数组类包含长度信息
- 数组类能够主动发现越界访问
3、Array设计要点
- 抽象类模板,存储空间的位置和大小由子类完成
- 重载数组操作符,判断访问下标是否合法
- 提供数组长度的抽象访问函数
- 提供数组对象间的复制操作
4、Array类的声明

5、编程实验:数组抽象类实现
Array.h
#ifndef ARRAY_H_
#define ARRAY_H_
/***
* Include Files *
***/
#include "Object.h"
#include "Exception.h"
/***
* Type Definition *
***/
namespace DTLib
{
template < typename T >
class Array : public Object
{
protected:
T* m_array;
public:
/**
* Function: set()
* Description: 设置数组下标为i的元素值为e
* Input: i 下标为i
* e 元素值为e
* Output:
* Return: bool 返回是否成功
* Others: 与原生数组差异:预防下标越界
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
virtual bool set(int i, const T& e)
{
bool ret = ((0 <= i) && (i < length()));
if( ret )
{
m_array[i] = e;
}
return ret;
}
/**
* Function: get()
* Description: 获取数组下标为i的元素值
* Input: i 下标为i
* e 元素值为e
* Return: bool 返回是否成功
* Others: 与原生数组差异:预防下标越界
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
virtual bool get(int i, T& e) const
{
bool ret = ((0 <= i) && (i < length()));
if( ret )
{
e = m_array[i];
}
return ret;
}
/**
* Function: operator[]()
* Description: []操作符重载函数
* Input: i 数组下标i的元素
* Output:
* Return: T 返回元素的值
* Others: 下标越界,抛出异常
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
virtual T& operator[] (int i)
{
if((0 <= i) && (i < length()))
{
return m_array[i];
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ...");
}
}
/**
* Function: operator[]()
* Description: []操作符重载函数(传入const)
* Input: i 数组下标i的元素
* Output:
* Return: T 返回元素的值
* Others: 下标越界,抛出异常
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
virtual T operator[] (int i) const
{
return (const_cast<Array<T>&>(*this))[i];
}
/**
* Function: array()
* Description: 返回数组的地址
* Input:
* Output:
* Return: T 返回数组的地址
* Others:
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
T* array() const
{
return m_array;
}
Array<T>& self()
{
return *this;
}
virtual int length() const = 0;
};
}
#endif // ARRAY_H_6、StaticArray设计要点
- 类模板
- 封装原生数组
- 使用模板参数决定数组大小
- 实现函数返回数组长度
- 拷贝构造和赋值操作
7、StaticArray类的声明

8、编程实验:静态数组类的实现
StaticArray.h
#ifndef STATICARRAY_H_
#define STATICARRAY_H_
/***
* Include Files *
***/
#include "Array.h"
/***
* Type Definition *
***/
namespace DTLib
{
template < typename T, int N >
class StaticArray : public Array<T>
{
protected:
T m_space[N];
public:
StaticArray() // 构造函数
{
this->m_array = m_space; // 初始化父类成员
}
StaticArray(const StaticArray<T, N>& obj) // 拷贝构造函数
{
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) // 赋值构造函数
{
if( this != &obj ) // 不允许自赋值
{
for(int i=0; i<N; i++) // 循环赋值
{
m_space[i] = obj.m_space[i];
}
}
return *this; // 返回当前类的指针,代表允许连续赋值
}
int length() const // 返回数组的成员数量
{
return N;
}
};
}
#endif // STATICARRAY_H_9、实战预告
To be continued …

二十、数组类的创建(下)
1、课程目标
完成DynamicArray 类的具体实现

2、DynamicArray设计要点
- 类模板
- 动态确定内部数组空间的大小
- 实现函数返回数组长度
- 拷贝构造和赋值操作
3、DynamicArray类的声明

4、编程实验:动态数组的实现
5、问题
DynamicArray类中的函数实现存在重复的逻辑,如何进行代码优化?
6、重复代码逻辑的抽象
init
对象构造时的初始化操作
copy
在堆空间中申请新的内存,并执行拷贝操作
update
将指定的堆空间作为内部存储数组使用
7、编程实验:动态数组的优化
DynamicArray.h
#ifndef DYNAMICARRAY_H_
#define DYNAMICARRAY_H_
/***
* Include _Files *
***/
#include "Array.h"
#include "Exception.h"
/***
* Type Definition *
***/
namespace DTLib
{
template < typename T >
class DynamicArray : public Array<T>
{
protected:
int m_length;
/**
* Function: copy()
* Description: 动态调整数组大小
* Input: array 数组类地址
* len 原数组成员数量
* newLen 新数组成员数量
* Output:
* Return: bool 返回数组类地址
* Others: O(n)
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
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;
}
/**
* Function: update()
* Description: 动态调整后更新
* Input: array 数组类地址
* length 数组元素数量
* Output:
* Return:
* Others:
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
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 ...");
}
}
/**
* Function: init()
* Description: 初始化数组大小
* Input: array 数组类地址
* length 数组元素数量
* Output:
* Return:
* Others:
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
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:
/**
* Function: DynamicArray()
* Description: 构造函数 - 创建数组
* Input: length 数组元素数量
* Output:
* Return:
* Others:
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
DynamicArray(int length = 0)
{
init(new T[length], length);
}
/**
* Function: DynamicArray()
* Description: 拷贝构造函数
* Input: obj 待拷贝的数组类
* Output:
* Return:
* Others: 先创建拷贝数组类(copy),再初始化数组地址和数组元素数量(init)
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
DynamicArray(const DynamicArray<T>& obj)
{
init(copy(obj.m_array, obj.m_length, obj.m_length), obj.m_length);
}
/**
* Function: operator=()
* Description: 赋值构造函数
* Input: obj 待拷贝的数组类
* Output:
* Return:
* Others: 先创建拷贝数组类(copy),再更新数组地址和数组元素数量(update)
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
DynamicArray<T>& operator= (const DynamicArray<T>& obj)
{
if( this != &obj ) // 禁止自赋值
{
update(copy(obj.m_array, obj.m_length, obj.m_length), obj.m_length);
}
return *this;
}
/**
* Function: length()
* Description: 返回数组元素数量
* Input:
* Output:
* Return: 返回数组元素数量
* Others:
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
int length() const
{
return m_length;
}
/**
* Function: resize()
* Description: 重新分配数组的元素数量
* Input: length 重新分配的数组元素数量
* Output:
* Return:
* Others: 先创建拷贝数组类(copy),再更新数组地址和数组元素数量(update)
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
virtual void resize(int length)
{
if( length != m_length )
{
update(copy(this->m_array, m_length, length), length);
}
}
/**
* Function: ~DynamicArray()
* Description: 析构函数
* Input:
* Output:
* Return:
* Others: 释放数组的堆空间
* Modify Date Version Author Modification
* ------------------------------------------------------------
* 2022/03/10 1.0 Create
**/
~DynamicArray()
{
delete[] this->m_array;
}
};
}
#endif // DYNAMICARRAY_H_8、小结
- StaticArray通过封装原生数组的方式实现数组类
- DynamicArray动态申请堆空间,使得数组长度动态可变
- 数组对象能够代替原生数组,并且使用上更安全
- 代码优化是项目开发过程中不可或缺的环节
