写在文章开头的话
读完这篇文章后,你将学习到下面的知识:
(1)一个多维数组是如何工作的
(2)如何重载二维数组下标
1. 分析
读完这篇文章后,你将学习到下面的知识:
(1)一个多维数组是如何工作的
(2)如何重载二维数组下标
1. 分析
重载一维数组下标很简单,通过下标传入的索引值,返回内部数组中相应的值。那重载二维数组的下标运算呢?
其实重载二维和一维本质是一样的,因为 C/C++ 中所谓的 “二维或多维数组”都是由简单的一维数组表示的。举个例子哈:
下面是两个 int 数组,第(1)个是熟悉的一维数组,第(2)个是熟悉的二维数组,现在你要做的就是将第(2)个数组看成是一个一维数组。
(1)int array[3];
(2)int array[3][4];
怎么看?可以在头脑中将第(2)个数组数组看成如下定义的方式, 数组 array 包含 3 个元素,其中每个元素又都是一个数组类型(或者说是一个指针类型)。
typedef int T[4];
T array[3];
至于更高维数的数组,也是这样看,比如如下的三维数组,可以采用下面的方式来定义。
- int array[3][4][5];
- typedef int T1[5];
- typedef T1 T2[4];
- T2 array[3];
由于实际中二维数组用的较多,所以,下面主要是练习二维数组的下标重载。那重载二维数组的下标有什么好处呢?最大的好处就在于可以使代码简洁直观。
我在网上也看到过一些别人的实现方法,其中在 文章( http://edu.gamfe.com/tutor/d/24416.html)中就提到了一种重载方法,使用一维数组来表示二维数组,这是大多数的实现方法,但是其实现过程过于复杂,其构建了两个类,分别用来获取行和列,然后计算出指定的二维下标对应的内部一维数组的值并返回。
下面介绍我自己写重载二维下标实现方式,不一定最好,但比上面提到的方式要好。
2. 重载固定维数的二维数组下标
- struct Matrix4f
- {
- float m[4][4];
- float * const operator[](const int i)
- {
- return m[i];
- }
- };
测试赋值和取值操作,均正常:
- Matrix4f m;
- m[0][0] = 1.0f;
- m[1][1] = 9.9f;
- cout << m[0][0] << endl; // 1
- cout << m[1][1] << endl; // 9.9
3. 重载维数可变的二维数组下标
- template <typename T>
- class Matrix
- {
- public:
- Matrix(int row, int col)
- :m_row(row), m_col(col), m_data(nullptr)
- {
- m_data = new T[m_row * m_col];
- }
- ~Matrix()
- {
- if (m_data != nullptr)
- {
- delete[] m_data;
- m_data = nullptr;
- }
- }
- // 返回二维数组的第 k 行地址,注意加上 const 因为数组地址是不可变的
- T * const operator[](int k)
- {
- return &m_data[k * m_col];
- }
- private:
- int m_row;
- int m_col;
- T *m_data;
- };
其中 operator[] 返回 T * const 类型是因为数组首地址是常量,防止非法的赋值操作,例如:
- int arr1[3][4];
- int arr2[3][4];
- arr1[0] = arr2[0]; // ERROR!
测试赋值和取值操作:
- Matrix<int> m2(3, 4);
- m2[0][0] = 2;
- m2[2][3] = 9;
- cout << m2[0][0] << endl; // 2
- cout << m2[2][3] << endl; // 9
和一般的二维数组一样没有越界检查,所以越界操作也是可以的,但是尽量使用前检查索引是否越界,以免引发未知错误。
转载请注明出处:http://blog.csdn.net/xiaohui_hubei/article/details/21334141