课程目标
完成 DynamicArray 类的具体实现
DynamicArray 设计要点
类模板
- 动态确定内部数组空间大小
- 实现函数返回数组长度
- 拷贝构造和赋值操作
DynamicArray 类的声明
template <typename T>
clas DynamicArray : public Arrray<T>
{
public:
DynamicArray(int length);
DynamicArray(const DynamicArray<T> &obj);
DynamicArray<T> &operator= (const DynamicArray<T> &obj);
int length() const;
void resize(int length);
protected:
int m_length;
};
编程实验:动态数组的实现
#ifndef DYNAMICARRAY_H
#define DYNAMICARRAY_H
#include "Array.h"
#include "Exception.h"
namespace DTLib
{
template <typename T>
class DynamicArray : public Array<T>
{
public:
DynamicArray(int length = 0) // O(1)
{
this->m_array = new T[length];
if (this->m_array != nullptr)
{
this->m_length = length;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create DynamicArray object ...");
}
}
DynamicArray(const DynamicArray<T> &obj) // O(n)
{
this->m_array = new T[obj.m_length];
if (this->m_array != nullptr)
{
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) // O(n)
{
if (this != &obj)
{
T *array = new T[obj.m_length];
if (array != nullptr)
{
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 DynamicArray object ...");
}
}
return *this;
}
int length() const // O(1)
{
return m_length;
}
void resize(int length) // O(n)
{
if (length != m_length)
{
T *array = new T[length];
if (array != nullptr)
{
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 DynamicArray object...");
}
}
}
~DynamicArray() // O(1)
{
delete [] this->m_array;
}
protected:
int m_length = 0;
};
}
#endif // DYNAMICARRAY_H
文件:main.cpp
#include <iostream>
#include "DynamicArray.h"
using namespace std;
using namespace DTLib;
int main()
{
cout << "main begin" << endl;
DynamicArray<int> d(5);
for (int i=0; i<d.length(); ++i)
{
d[i] = i * i;
}
for (int i=0; i<d.length(); ++i)
{
cout << d[i] << endl;
}
cout << "---------" << endl;
DynamicArray<int> d1;
d1 = d;
d1.resize(3);
for (int i=0; i<d1.length(); ++i)
{
cout << d1[i] << endl;
}
cout << "main end" << endl;
return 0;
}
输出:
main begin
0
1
4
9
16
---------
0
1
4
main end
问题:
DynamicArray 类中的函数实现存在重复的逻辑,如何进行代码优化?
重复代码逻辑的抽象
init
- 对象构造时的初始化操作
copy
- 在堆空间中申请新的内存,并执行拷贝操作
update
- 将指定的堆空间作为内存存储数组使用
编程实验:动态数组的优化
#ifndef DYNAMICARRAY_H
#define DYNAMICARRAY_H
#include "Array.h"
#include "Exception.h"
namespace DTLib
{
template <typename T>
class DynamicArray : public Array<T>
{
public:
DynamicArray(int length = 0) // O(1)
{
init(new T[length], length);
}
DynamicArray(const DynamicArray<T> &obj) // O(n)
{
init(copy(obj.m_array, obj.m_length, obj.m_length), obj.m_length);
}
DynamicArray<T> &operator= (const DynamicArray<T> &obj) // O(n)
{
if (this != &obj)
{
update(copy(obj.m_array, obj.m_length, obj.m_length), obj.m_length);
}
return *this;
}
int length() const // O(1)
{
return m_length;
}
void resize(int length) // O(n)
{
if (length != m_length)
{
update(copy(this->m_array, this->m_length, length), length);
}
}
~DynamicArray() // O(1)
{
delete [] this->m_array;
}
protected:
int m_length = 0;
T *copy(T *array, int length, int newLength) // O(n)
{
T *ret = new T[newLength];
if (ret != nullptr)
{
int size = (length < newLength) ? length : newLength;
for (int i=0; i<size; ++i)
{
ret[i] = array[i];
}
}
return ret;
}
void update(T *array, int length) // O(1)
{
if (array != nullptr)
{
T *temp = this->m_array;
this->m_array = array;
this->m_length = length;
delete [] temp;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory to update DynmicArray object ...");
}
}
void init(T *array, int length) // O(1)
{
if (array != nullptr)
{
this->m_array = array;
this->m_length = length;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No enough to init DynamicArray object ...");
}
}
};
}
#endif // DYNAMICARRAY_H
小结
- StaticArray 通过封装原生数组的方式实现数组类
- DynamicArray 动态申请堆空间,使得数组长度动态可变
- 数组对象能够代替原生数组,并且使用上更安全
- 代码优化是项目开发中不可或缺的环节
以上内容整理于狄泰软件学院系列课程,请大家保护原创!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。