运算符重载实例:可变长整型数组

问题

写一个可变长整型数组类CArray,并且满足以下程序的正常运行

int main(){
    CArray a;
    for(int i = 0; i < 5; ++i){
        a.push_back(i);
    }
    CArray a2, a3;
    a2 = a;
    for(int i = 0; i < a.length(); ++i){
        cout << a2[i] << " ";
    }
    a2 = a3;
    for(int i = 0; i < a2.length(); ++i){
        cout << a2[i] << " ";
    }
    cout << endl;
    a[3] = 100;
    CArray a4(a);
    for(int i = 0; i < a4.length(); ++i){
        cout << a4[i] << " ";
    }
    return 0;
}

程序输出结果

0 1 2 3 4
0 1 2 100 4

分析

需求分析

  1. CArray需要两个成员变量arrlen,整型指针arr指向动态分配的数组,整型len表示数组元素的个数.
  2. 构造函数.可以缺省的指定数组长度(程序中没有强求).
  3. 复制构造函数.支持CArray a4(a);语句的正确执行.在执行初始化语句时会调用复制构造函数构造对象,为了避免使用默认的复制构造函数而引起的浅拷贝的问题,需要自己重写复制构造函数.
  4. 析构函数.释放动态分配的数组内存.
  5. push_back(int i)成员函数.用于在数组尾部添加一个元素i.
  6. 重载运算符=.用于数组对象间的赋值
  7. length()成员函数.返回数组元素的个数
  8. 重载运算符[].支持n=a[i];a[i]=4;这样的语句.

代码实现分析

构造函数CArray(int l = 0);

缺省数组长度的构造函数,当指定数组长度时开辟相应长度的数组空间,否则初始为NULL.

复制构造函数CArray(CArray& a);

用同类对象对对象初始化时会调用复制构造函数初始化对象,如语句CArray a4(a);.为了避免浅拷贝的问题,需要重写复制构造函数.在复制构造函数中,为新的对象重新分配一片存储空间,避免和之前的对象a指向同一片内存空间.首先判断一下a是否为NULL,如果为NULL,则直接将数组指针指向NULL即可,否则新开辟一块a.len大小的内存空间,使用memcpy内存拷贝函数进行数据拷贝,最后设置好数组长度.

析构函数~CArray();

在释放内存空间之前,避免重复释放内存出错,先判断一下数组指针arr是否为NULL.

添加数组元素push_back(int i);

如果数组本来不为空,分配一个比原来长度加一的内存空间,赋给一个临时数组指针,然后将原来的数组内容拷贝到这个临时的数组中,然后再释放原来的内存空间,然后让数组指针指向刚才分配的那片内存的地址.如果数组本来为空,则只需要分配一个长度为1的内存空间.最后,向数组尾部加入新的数组元素,并且更新数组长度.
补充:老师说该方式效率较低,可以采取每次内存不够的时候分配两倍大的空间,可以减少分配内存空间的次数.我思考了一下,如果采取这种办法的话就需要两个成员变量sizelen,size指示内存空间的大小,len指示当前数组元素,才可以实现.

重载运算符=`CArray& operator=(const CArray& a);`

为了实现变长数组对象之间的正确赋值,避免浅拷贝问题,在重载=运算符时,=左右两边的数组对象大小和内容都一样,但不在同一片内存空间.那么思考一个问题,当遇到a=a;语句时,会出现什么现象?为了避免a=a;这样的赋值出错,首先应该先判断一下=左右两边的对象是否相等,如果相等则直接返回本对象.接下来考虑两个对象不等的情况.
-1- 如果右边的对象a里面的数组是空的,则释放本对象数组内存,并且将数组指针赋为NULL,更新len0,返回本对象的引用;
-2- 如果原来的数组对象中有足够大的空间,不需要再重新分配新的内存空间.否则释放原有空间,分配新的内存空间.
-3- 拷贝右边对象a中的数据,更新len,返回本对象的引用,结束.

重载运算符[] int& operator[](int index);

注意要支持n=a[i];a[i]=4;这样的语句,返回值为int&.

完整代码

#include<iostream>
#include<string.h>
using namespace std;
//可变长数组对象
class CArray{
public:

    //构造函数,l代表数组元素的个数
    CArray(int l = 0);

    //复制构造函数
    CArray(CArray& a);

    //析构函数
    ~CArray();

    //取长度,返回元素个数
    const int length();

    //插入函数,用于在数组尾部添加一个元素i
    void push_back(int i);

    //重载=,用于可变长数组对象间的赋值
    CArray& operator=(const CArray& a);

    //重载[],支持n=a[i];和a[i]=4;这样的语句,返回值为int&
    int& operator[](int index);

private:
    int len;                                    //数组元素的个数
    int* arr;                                   //指向动态分配的数组
};

//构造函数
CArray::CArray(int l):len(l){
    if(0 == l){
        arr = NULL;
    }else{
        arr = new int[l];
    }
}

//复制构造函数
CArray::CArray(CArray& a){
    if(!a.arr){
        arr = NULL;
        len = 0;
        return;
    }
    arr = new int[a.len];
    memcpy(arr, a.arr, sizeof(int)*a.len);
    len = a.len;
}

//析构函数
CArray::~CArray(){
    if(arr){
        delete[] arr;
    }
}

//插入函数
void CArray::push_back(int i){
    if(arr){
        int* arrCpy = new int[len+1];
        memcpy(arrCpy, arr, sizeof(int)*len);
        delete[] arr;
        arr = arrCpy;                           //数组之间赋值
    }else{
        arr = new int[1];
    }
    arr[len++] = i;                             //加入新的数组元素
}

//重载=
CArray& CArray::operator=(const CArray& a){
    if(arr == a.arr){                           //a=a;
        return *this;
    }
    if(!a.arr){
        if(arr){
            delete[] arr;
        }
        arr = NULL;
        len = 0;
        return *this;
    }
    if(len < a.len){
        if(arr){
            delete[] arr;
        }
        arr = new int[a.len];
    }
    memcpy(arr, a.arr, sizeof(int)*a.len);
    len = a.len;
    return *this;
}

//重载[]
int& CArray::operator[](int index){
    if(index < 0 || index > length()){
        return arr[0];
    }else{
        return arr[index];
    }
}

//取长度
const int CArray::length(){
    return len;
}

int main(){
    CArray a;
    for(int i = 0; i < 5; ++i){
        a.push_back(i);
    }
    CArray a2, a3;
    a2 = a;
    for(int i = 0; i < a.length(); ++i){
        cout << a2[i] << " ";
    }
    a2 = a3;
    for(int i = 0; i < a2.length(); ++i){
        cout << a2[i] << " ";
    }
    cout << endl;
    a[3] = 100;
    CArray a4(a);
    for(int i = 0; i < a4.length(); ++i){
        cout << a4[i] << " ";
    }
    return 0;
}

afra
225 声望23 粉丝

你的努力程度之低 远还没有到比拼天赋的需要。