写在前面
- 选择记录本题是因为在如何表示二维数组的指针,以及如何传递二维数组的指针时遇到了问题,说明对指针的理解还不够透彻,暂时记录下基于本次练习的思考经过
关于二维数组指针的理解
首先明确指针和元素的表示方法,否则后面的理解就无从谈起
-
数组的指针具有2重含义
- 整体指向:指向整个数组所在的内存块
- 首元素指向:指向数组的首元素所在内存块
-
指针可以用两种方式表示(假如有数组 int a[5], 则):
- 数组名表示法,即直接用a表示指向此数组的指针
- 指针名表示法,如 int* ptr= &a[0],ptr就是指针所在内存块的名称
-
数组中的元素也可以用两种方式表示
- 数组名表示法,如 a[0],a[1],这都是用数组名+方括号来表示元素
- 指针名表示法,如ptr[0],ptr[1],这都是是用指针名+方括号来表示元素
理解一维数组和二维数组的指针与元素的关系,见图
-
一维数组
-
二维数组,第1维是行,第2维是列
二维数组指针的两种用法
int(*ptr)[5]
,这里ptr is a pointer to an array int[5]- 优点是通突出显示所指向的数组中元素的个数
- 缺点是不够灵活,向函数传递指针时会限定一维数组的元素个数,无法增加或减少
int** ptr
,这就相当于是(int*)* ptr
,意为 ptr is a pointer to an arry of int*[5],然后对于每个元素(每个元素均为指针)再指向动态创建的一维数组- 优点是可以灵活指向不同一维元素数量的数组
- 缺点是初学者容易不理解这是二维数组的指针,只要掌握关键,即由若干个int*构成第1维,每个int*再指向若干int构成的第2维
将二维数组用一维数组的方式进行理解
- 一维数组中,包含若干个元素,每个元素因不能再进一步细分为更小的元素,可称为单元素
- 二维数组中,也包含若干个元素,只不过每个元素都是一个一维数组,这里的每个一维数组可以称为行元素,或者大元素。每个行元素可以进一步细分为若干个单元素(自己为便于理解胡乱起的名,特备注)
补充:但凡可以配合方括号表示具体元素的,都可以用作指针
- 二维数组a[3][5]中,为什么
a[0],a[1],a[2]
可以表示指针?如int* ptr = a[1]
- 因为但凡可以配合方括号表示具体元素的,都可以用作指针,如
a[1][3]
就表示二维数组中的具体元素,其中a[1]
是当作第2维数组中的某一维的数组名或指针名使用的,所以它可以用作指针
- 因为但凡可以配合方括号表示具体元素的,都可以用作指针,如
本题源码
#include <iostream>
#include <iterator>
#include <algorithm>
template<class T>
void changeLength2D(T**a, int theIndexOf1D, int oldLen, int newLen)
{
// if out of range throw exception. theIndex1D, newLen
T* temp = new T[newLen];
int number = std::min(oldLen, newLen);
std::copy(a[theIndexOf1D], a[theIndexOf1D] + oldLen, temp);
delete a[theIndexOf1D];
a[theIndexOf1D] = temp;
}
int main()
{
// a is a pointer points to an array composed of 3 int*, also to an int* which is first element in array
int** a = new int*[3];
for(int i = 0; i < 3; i++)
a[i] = new int[5];
// b is a pointer points to int, the first element of line-element a[2]
int*b = a[2];
// fill all element with value "10"
std::fill(b, b + 5, 10);
std::copy(b, b + 5, std::ostream_iterator<int>(std::cout, " "));
changeLength2D<int>(a, 2, 5, 10);
std::cout << std::endl;
std::copy(b, b + 10, std::ostream_iterator<int>(std::cout, " "));
}