应该执行什么功能?
假设我们要实现一个将自动扩展的数组类,是否需要实现函数?让我们从下面主要功能使用的功能开始,看看我们需要实现哪些功能。
输出结果:
0 1 2 3 4
0 1 2 100 4
您需要做什么才能实现上述功能?首先列出:
若要使用动态分配的内存来存储数组元素,并且需要一个指针成员变量
重载分配=运算符
重载括号[]运算符
重载的副本构造函数
实现push_back和length函数
- 2 -
实现步骤
要实现可变长度数组类,您基本上需要实现以下7个功能:
01构造函数
构造函数的目的是初始化一个数组,代码如下:
// 构造函数MyArray::MyArray(int s = 0):m_size(s){ // 当初始化长度为0的数组时,数组指针就是空的 if(s == 0) m_ptr = NULL; // 当初始化长度不为0时,则申请对应大小的空间 else m_ptr = new int[s];
02复制构造函数
复制构造函数的目的是产生一个与输入对象相同的对象,但是由于MyArray类具有指针成员变量,因此必须使用深层复制来实现复制构造函数。如果使用默认的复制构造函数,则使两个对象的指针成员变量指向同一地址将非常危险。
// 复制构造函数MyArray::MyArray(const MyArray &a){ // 如果入参的数组对象的指针地址为空时, // 则也初始化一个空的数组 if(a.m_ptr == NULL) { m_ptr = NULL; m_size = 0; } // 如果入参的数组对象有数据时,则申请一个新的地址, // 最后来复制入参对象数组对象的数据和大小。 else { m_ptr = new int[a.m_size]; memcpy(m_ptr, a.m_ptr, sizeof(int)*a.m_size); m_size = a.m_size; }}
03析构函数
析构函数的目的是释放数组的资源,代码如下:
// 析构函数MyArray::~MyArray(){ // 如果指针地址不为空时,则释放资源 if(m_ptr) delete [] m_ptr;}
04 重载分配=运算符函数
重载分配=运算符函数目的就是 = 号左边对象里存放的数组,大小和内容都和右边的对象一样,代码如下:
// 重载赋值 = 运算符函数MyArray & MyArray::operator=(const MyArray & a){ if(m_ptr == a.m_ptr) // 防止a=a这样的赋值导致出错 return *this; if(a.m_ptr == NULL) // 如果a里面的数组是空的 { if(m_ptr) delete [] m_ptr; // 释放旧数组的资源 m_ptr = NULL; m_size = 0; return *this; } // 如果原有空间足够大,就不用分配新的空间 if(m_size < a.m_size)用分配新的空间 { if(m_ptr) delete [] m_ptr; // 释放旧数组的资源 m_ptr = new int[a.m_size]; // 申请新的内存地址 } // 拷贝内容 memcpy(m_ptr, a.m_ptr, sizeof(int)*a.m_size); m_size = a.m_size; return *this;}
05重载[]操作符功能
重载[]运算符功能的目的是通过[]运算符获取相应下标的数组值,代码如下:
// 重载[]运算符函数int & MyArray::operator[](int i){ return m_ptr[i]; // 返回对应下标的数组值}
06将元素添加到数组末尾的函数
push_back函数的目的是在数组的末尾添加一个新元素,代码如下:
// 在数组尾部添加一个元素void MyArray::push_back(int v){ if(m_ptr) // 如果数组不为空 { // 重新分配空间 int *tmpPtr = new int[m_size + 1]; // 拷贝原数组内容 memcpy(tmpPtr, m_ptr, sizeof(int)*m_size); delect [] m_ptr; m_ptr = tmpPtr; } else // 如果数组本来就是空的 { m_ptr = new int[1]; } m_ptr[m_size++] = v; //加入新的数组元素}
07获取数组长度的函数
长度函数相对简单。它直接返回成员变量m_size,即数组的长度。代码如下:
// 获取数组长度的函数int MyArray:;length(){ return m_size;}
— 04 —— 04 —
改进它?
push_back函数仍有优化的空间。每次添加元素时,当前的push_back函数都会重新分配新的内存,这会增加开销。
然后是优化思想:预先分配大小为n的空间,当数组大小不足时,然后继续重新分配2n大小的空间,依此类推。
我们需要添加两个成员变量:
int m_cout; // 数组元素的个数 int m_newNum; // 扩容的次数
改进的push_back函数,代码如下:
— 5 —— 5 —
概要
最后,总体代码如下: