我试图理解2D数组的动态分配在C++中是如何在内部工作的。
在为int
类型和大小为m * n
的2D数组动态分配内存时,我们写:int **arr = new int * [m];
然后在大小m
上运行一个循环,直到达到列数n
,为每个指针分配一个数组。
我不明白为什么我们假设当我们创建指针数组时,它假设它是行格式的。为什么它不能是列格式的?如果它是列格式的,那么当我们迭代它分配数组时,我们就会分配行,因此2D数组的顺序会颠倒,而不是m * n
,它会变成n * m
。
系统如何知道这个语句-int **arr = new int * [m]
-必须以行格式分配,而相应的列将在以后分配?
3条答案
按热度按时间nx7onnlm1#
标准的C语言确实在一个块中分配多维的“C数组”,而不是像文本所描述的那样。所以
int arr[3][4]
将被分配(等效地)为int arr[12]
,arr[2][1]
将被访问为arr[2*4+1]
。然而,即使对于小矩阵,这也会造成内存碎片(块太大而无法分配),因此软件包通常会像您的文本描述的那样独立分配整个列或行。
相反,Fortran将按行分配矩阵,所以你在编码时需要注意这一点。在C语言中没有类似的东西。
因此,单个元素的内部分配和访问完全取决于您使用的包。
nnvyjq4y2#
由您决定是要以行为主还是以列为主的二维数组分配方案。
**arr = new int * [m]
m可以是列或行的计数。系统与此无关。更重要的是你什么时候选择row-major还是column-major。这可能取决于你选择的算法,或者性能要求。例如,如果你通过迭代行来访问你的2D数组,那么row-major将更有效,因为CPU将在更有效的缓存中缓存行。另一方面,如果你通过列来迭代你的数组,那么选择column-major。
还有其他方法来分配内存,将其用作2d数组-通过调用
int* arr = new int[m*n];
然后使用arr[i + j*m]
进行索引,假设m是针对行的。yws3nbqq3#
你所描述的不是一个2D数组,而是一个指向1D数组的指针的1D数组。这取决于应用程序来决定这些指针是表示矩阵的行还是列。
在C和C++中,可以定义2D数组,并以行优先顺序存储,这意味着连续存储的元素具有连续的第二个索引。在内存中,A[1][0]后面紧跟着A[1][1]。考虑到第一个[第二个]索引通常被称为表示行[列],这证明了行优先命名的合理性。
为了一致性,指向数组的指针数组应该与连续的行相对应。