数字收件人中的内存分配c ++

时间:2017-05-23 08:39:51

标签: c++

在内存分配方面:

let int a [i] [j] = {matrix as below}

enter image description here

现在,如果我定义指针* p =& a [0] [0],那么我可以得到一个函数 *(p +((o-1)* 4 + j-1)(其中4代表int的位数)

因此是2,它在c ++中,因为我们从0开始而不是1等于1 *(p +((2-1) 4)+(2-1))= (a + 4 + 1的地址)= 6.

现在这对我有意义,并且希望它是正确的,但如果我的推理不是,请告诉我。

接下来阅读数字引导指南..我看到了这一点:

enter image description here

但是第一种方法的公式不像我的那样,我缺少什么? enter image description here

现在在第二种情况下我们创建一个双指针** a,这是一个指针列表,其中每个元素指向一行?它是一行还是它指向的列。

因为如果它是一行,那么在以下面的方式分配内存时我会感到困惑:

int rows;
int columns;
double **correls=Null;

for(int i=0;i<columns;i++){correls[i]= new double [columns];}

我只是不明白为什么我们从i计数到-1列,因为我相信我们在底部的照片中有一列指针,我们需要指针向量中的每个元素,指向到一个新的元素向量,因此为什么不相关[行]而不是列的计数。我知道我们分配一个新的向量作为这样的新的double [columns],因为指针向量中的每个指针指向具有如下定义的列数的元素的特定向量。

感谢我能得到的所有帮助!

谢谢:)

3 个答案:

答案 0 :(得分:1)

在C

中创建2D数组有两种合理的方法
int array[4][5];

int **array;
array = malloc(4 * sizeof(int *));
for(i=0;i<4;i++)
  array[i] = malloc(5 * sizeof(int));

现在C的一个小故障或怪癖是,这两个数组的语法是相同的

array[i][j] = x;

Numerical Recipes最初是用Fortran和数学家而不是程序员编写的。因此,他们为代码带来了一个以Fortran为中心的视图。

在C ++中,使用向量进行自动内存管理和边界检查是正常的。然而,由于C ++开销,复杂程序的算法核心通常用C或C ++编写,它实际上是C语言。 Numerical Recipes为您提供通常的算法核心。

答案 1 :(得分:0)

  

现在在第二种情况下我们创建一个双指针** a,这是一个指针列表,其中每个元素指向一行?

您可以确定指向的数组是行,是。

  

是一行还是它指向的列。

请记住,a是指向数组第一个元素的指针。如果您已确定数组元素指向的数组表示行,则a指向指向行的第一个指针。

  

我只是不明白为什么我们从i计数到-1列,因为我相信我们有一列指针

显然,编写该代码的人决定correls的每个元素都指向一个代表一列的数组。因此,您有一个指向列数组的指针,这些列是指向行的指针数组。

总结:有两种表示2D数组的方法:行主要顺序和列主要顺序。每个都是另一个的转置。

PS。不要在C ++中手动分配动态内存。而是使用诸如std::vector之类的RAII容器。另外,在阅读C指南时要小心。它们会引导你误入歧途,例如建议手动记忆分配。

PPS。不要理会这句话:

  

没有乘法;一个额外的间接取代它。因此,我们通常拥有比前一个更快更通用的方案

这是假的:间接可能需要一个比乘法慢几十亿倍的内存访问。动态可调大小的多功能性是指针数组的优势。

答案 2 :(得分:0)

免责声明:在C ++中,高级操作绝不应使用原始指针或原始数组。应始终包含它们(隐藏)是通过构造函数,析构函数和方法在OO模式中干净地使用的类。因此,本答案的其余部分假设您构建了一个专门的容器,您可以在其中使用低级操作。

您的初始示例使用现有的2D数组,只是严重分配指向行的指针数组。但它代码很差:

  • 如果C你应该从不施放malloc的结果
  • 如果是C ++,你根本不应该使用malloc

但无论如何动态分配是一个相当复杂的操作,涉及一个辅助工作,找到要使用的实际内存,将其标记为已使用,存储分配的长度以供以后在释放时使用,最终保持免费列表块等等。

所以你应该避免一次分配一行。它在语义上是正确的,但是效率低下的算法。对整个数组使用一个大的分配要好得多,即使你打算通过指针使用它 - 如果你要构建一个可以在很多地方使用的自定义容器,这一点非常重要。

您使用以下可能的(低级别)C ++代码结束:

  • 一次分配一行(效率低但正确):

    int rows;
    int columns;
    double **correls;
    
    // set rows and columns at their values...
    
    correls = new (double *)[rows];
    for (int i=0; i<rows; i++) correls[i] = new double[colums];
    
    // you can now safely use correls[i][j] with 0<=i<rows and 0<=j<columns
    
  • 在一次操作中分配一个大的1D数组:

    int rows;
    int columns;
    double **correls;
    
    // set rows and columns at their values...
    
    correls = new (double *)[rows];
    _array = new double[rows * columns];
    for (int i=0; i<rows; i++) correls[i] = _array + i * columns; // or &(_array[i * columns])
    
    // you can now safely use correls[i][j] with 0<=i<rows and 0<=j<columns
    

这些方法允许您分配其大小仅在运行时已知的动态数组。请记住,即使它们被普通编译器接受为扩展,标准C ++也不支持可变长度数组......