使用一维数组(或整数)我知道如何为堆和堆栈中的分配创建指针
- 堆栈中的堆栈和堆栈中的数组
int a[3];
int *ptr=a;
- 堆中的堆和堆中的数组
int *ptr=new int[3];
但是对于矩阵(例如3x2),指针可以创建为指针数组int (*A)[3]
或双指针int **A
。
我想知道创建指向多维数组的指针的这两种方式之间的主要区别。
特别是我看到用于创建存储在堆栈中的矩阵数组指针的指针数组:
int A[2][3];
int (*ptr)[3]=A;
我已经看到用于堆中分配的矩阵的双指针
int **ptr= new *[3];
for(int i=0; i<=3; i++) int ptr[i]=new [2];
但是,是否也可以使用堆的指针数组和堆栈的双指针?
而且,更一般地说,指针数组和双指针之间的主要区别是什么?
答案 0 :(得分:1)
从C ++(2017)标准版(7.2阵列到指针转换)
1“N T数组”或“未知数组”的左值或右值 T“的绑定可以转换为”指向T“的类型的prvalue。该 应用临时物化转换(7.4)。 结果是 指向数组第一个元素的指针。
因此我们假设您有一个像这样的数组
T A[N1][N2]...[Nn];
其中T
是某种类型,[N1][N2]...[Nn]
是数组维度的非正式记录。然后这个声明也可以写成
T ( A[N1] )[N2]...[Nn];
要向数组的第一个元素声明一个pojnter,你所要做的就是在声明中用( A[N1] )
替换( *ptr )
。
T ( A[N1] )[N2]...[Nn];
T ( *ptr )[N2]...[Nn] = A;
例如从问题中取出声明
int A[2][3];
你可以像
一样重写它int ( A[2] )[3];
现在很容易声明一个指向数组第一个元素的指针
int ( *ptr )[3] = A;
取消引用指针,得到二维数组int[3]
类型的第一个“行”
另一方面,如果你有一个像
这样的指针数组的声明int * A[3];
可以像
一样重写int * ( A[3] );
然后获得一个你可以写的指针声明
int * ( *ptr ) = A;
与
相同int **ptr = A;
因此,取消引用指针,您将获得int *
类型的对象,而该对象又是指针。
所以这个宣言
int ( *ptr )[3] = A;
指向的对象是一维数组。例如,你可以写
std::cout << sizeof( *ptr ) << std::endl;
您将获得一个等于sizeof( int[3] )
等于3 * sizeof( int )
至于此声明
int * A[3];
int **ptr = A;
指向的对象是int *
类型的指针。如果要为此指针编写
std::cout << sizeof( *ptr ) << std::endl;
然后你会得到一个等于sizeof( int * )
让我们考虑一下这段代码
int **ptr = new int *[2];
for( int i = 0; i < 2; i++ ) ptr[i] = new int[3];
在第一个语句中,动态分配了int *[2]
类型的一维数组。
然后在循环中动态创建2个类型为int[3]
的数组,并将指向数组第一个元素的指针分配给先前分配的一维数组的元素。
因此,整体上有动态分配的3个数组:int *[2]
类型之一和int [3]
类型中的两个。也就是说,分配了三个不同的内存范围。
相反,你可以写
int ( *ptr )[3] = new int[2][3];
在这种情况下,动态分配只有一个二维数组,声明的指针ptr
指向数组的第一个“行”。也就是说,只分配了一个内存范围。