指针数组(* A)[]和双指针** A之间的区别

时间:2017-12-05 10:22:40

标签: c++ arrays pointers matrix heap

使用一维数组(或整数)我知道如何为堆和堆栈中的分配创建指针

- 堆栈中的堆栈和堆栈中的数组

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];

但是,是否也可以使用堆的指针数组和堆栈的双指针?

而且,更一般地说,指针数组和双指针之间的主要区别是什么?

1 个答案:

答案 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指向数组的第一个“行”。也就是说,只分配了一个内存范围。