[C++]重载二维数组下标 [ ][ ]实现二维矩阵

[C++]重载二维数组下标 [ ][ ]实现二维矩阵

1. 背景

实际项目中,经常需要用到动态分配二维数据。因此经常需要手写循环,来分配和初始化数组。如:

//首先分配一个指针数组
int** array = new int*[m];

//然后给指针数组中的指针分配内存
for (int i=0;i<m;i++)
{
    for (int j=0;j<n;j++)
    {
        array[i] = new int[n];
    }

}

虽然利用GSL等库可以完成相同的任务,但往往我们的项目中仅仅使用二维数组,并不需要复杂的矩阵运算;使用一维数组代替二维数组时,不能用array[i][j]的方式取值,没有二维数组直观。为了方便使用二维数组,本文使用一维数组,通过重载[]实现二维矩阵。

2. 分析

用一维数组代替二维数组分配内存,获得连续的内存空间。通过重载[],返回第K行地址,从而实现array[i][j]的方式取值。

3. 实现

#ifndef _MAT2_
#define _MAT2_
template <class T>
class Mat2
{
public:
    typedef T value_type;
    typedef T* pointer;
    typedef T* const pointer_conster;
    typedef const T& const_reference;
    typedef const T* const const_pointer_const;

public:
    typedef struct{
        int cols;
        int rows;
    }Size2;
    enum {ROW=1,COL=2};

public:
    /**
    *构造函数
    *参数:行数rows、列数cols和初始化值defaul
    *创建一个大小为rows*cols的矩阵,初始值全部为default
    */
    Mat2(const int rows,const int cols,const_reference default=0);
    /**
    *构造函数
    *参数:矩阵大小n和初始化值defaul
    *创建一个大小为n*n的矩阵,初始值全部为default
    */
    Mat2(const int n, const_reference default=0);
    /**
    *复制构造函数
    *参数:矩阵
    */
    Mat2(const Mat2& mat2);
    ~Mat2(void);

private:
    int rows;
    int cols;
    pointer array;

public:
    /**
    *求矩阵大小
    *返回值为Size2结构
    */
    const Size2 size();

    /**
    *求矩阵大小
    *参数值为Mat2:ROW或者Mat2:COL
    *参数值为Mat2:ROW时返回行数;位Mat2:COL时返回列数,否则返回-1
    */
    const int size(int type) const;

    /**
    *返回一维数组
    */
    const_pointer_const data(){return array;}

    /**
    *重载赋值运算符
    */
    Mat2& operator=(const Mat2& mat);

    /**
    *重载[]运算符
    */
    pointer_conster operator[](const int k);

    //用default值填充矩阵
    void fill(const_reference default);
};

//注意:在模板中使用嵌套名字时,需要用typename关键字区分::取得是类型还是静态变量
template<class T>
Mat2<T>::Mat2(const int m,const int n,typename Mat2<T>::const_reference default)
    :rows(m),cols(n),array(new value_type[rows*cols])
{
    fill(default);
}

template<class T>
Mat2<T>::Mat2(const int n,typename Mat2<T>::const_reference default)
    :rows(n),cols(n),array(new value_type[n*n])
{
    fill(default);
}

template<class T>
Mat2<T>::Mat2(const Mat2& mat)
{
    Mat2::Size2 size2 = mat.size();
    rows = size2.rows;
    cols = size2.cols;
    array = new value_type[rows*cols];
    memcpy(array,mat.data(),rows*cols*sizeof(value_type));
}

template<class T>
const typename Mat2<T>::Size2 Mat2<T>::size()
{
    Mat2::Size2 size2;
    size2.rows = rows;
    size2.cols = cols;
    return size2;
}

template<class T>
const int Mat2<T>::size(int type) const
{
    switch(type)
    {
    case Mat2::ROW:
        return rows;
    case Mat2::COL:
        return cols;
    }
    return -1;
}

template<class T>
typename Mat2<T>& Mat2<T>::operator =(const Mat2<T>& mat)
{
    if (this != &mat)//注意:防止自复制
    {
        if (array)
        {
            delete[] array;
        }
        Mat2::Size2 size2 = mat.size();
        rows = size2.rows;
        cols = size2.cols;
        array = new value_type[rows*cols];
        memcpy(array,mat.data(),rows*cols*sizeof(value_type));
    }
    return *this;
}

// 返回二维数组的第 k 行地址,注意加上 const 因为数组地址是不可变的
template<class T>
typename Mat2<T>::pointer_conster Mat2<T>::operator[](const int k)
{
    return &(array[k*cols]);
}

template<class T>
void Mat2<T>::fill(typename Mat2<T>::const_reference default)
{
    for (int i=0;i<rows;i++)
    {
        for (int j=0;j<cols;j++)
        {
            array[i*cols+j] = default;
        }
    }
}

template<class T>
Mat2<T>::~Mat2(void)
{
    if (array)
    {
        delete[] array;
    }
}

#endif // _MAT2_

猜你喜欢

转载自blog.csdn.net/chuqidecha/article/details/52278635
今日推荐