为什么顶层代码工作,底层代码不在c ++中进行动态矩阵分配? [英] Why does the top code work and the bottom code not in c++ for dynamic matrix allocation?

查看:289
本文介绍了为什么顶层代码工作,底层代码不在c ++中进行动态矩阵分配?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经摆脱了工作,因为他们分心的代码。
我想做的是为一个3D数组分配一块内存。



这是我当前的代码片段:

  //创建一个正确大小的数组
//我首先创建一个指针数组
phi = new double ** [xlength ];
//然后创建另一个指针数组
phi [0] = new double * [xlength * ylength];
//此时,我假设phi [0]和phi [0] [0]具有相同的位置。这不是真的吗?
phi [0] [0] = new double [xlength * ylength * tlength];
//现在,我分配了实际存储数据的大数据块
//我假设phi [0] [0] [0]与phi [0] [0] ]。这是正确的吗?
//现在,我试图设置指针在单个内存块中匹配
for(int i = 0; i {
for(int j = 0; j {
phi [i] [j] = phi [0] [0] + tlength * ylength * i + tlength *
}
}
//这不行吗?它感觉好像应该

回答工作代码,因为回答取决于工作代码

  double *** A = new double ** [m]; 
double ** B = new double * [m * n];
double * C = new double [m * n * o];
for(int i = 0; i for(int j = 0; j B [n * i + j] = C +(n * i + j)* o;
}
A [i] = B + n * i;
}
for(int i = 0; i for(int j = 0; j< n; j ++){
for 0; k A [i] [j] [k] =< my_value>
}
}

>



不要做3D矩阵,LOL!这是我最不受欢迎的帖子。



做一维矩阵,并按照此链接的答案 C ++分段故障后尝试写入矩阵



这是该链接的重要部分:



但是您不能使用phi [i] [j] [k]符号,因此您应该

  #define inphi(I,J,K)phi [(I)* xlength * ylength +(J)* xlength +(K)] $ b (i,j,k)而不是phi [i] [i]中写入 

j] [k]




  • 您不使用delete []释放分配的内存。这是一个很糟糕的做法

  • 非常不舒服,锯齿阵列(数组数组),用于长期使用。更容易的解决方案是分配一个数组:

      double * phi = new double [xlength * ylength]; 

    然后访问(x,y)元素如下:

      phy [y * xlength + x] = 20.0; 

    分配需要更少的时间,你有很少的东西要释放(只有phi本身)


  • 请考虑使用 std :: vector std :: array 。因为你使用C ++而不是C,自然的方式是使用这些容器而不是原始数组,它们更容易管理,如果静态分配,他们会自己释放它们的内容。在你的情况下,它看起来像:

      #include< vector& 

    (...)

    std :: vector< std :: vector< double> > ;

    phi.resize(xlength);
    for(int x = 0; x phi [x] .resize(ylength);




解决方案:



您的解决方案将无法运作。原因,为什么原始代码的作者使用三个变量是,其中一个必须包含实际数据,另外两个作为指针的原始数据的一部分。



在你的情况下,你试图保持数据和指向部分数据的指针在同一个数组,什么根本不能工作。如果你想要 [] [] [] 符号,你必须在嵌套循环中分配锯齿状数组,正如我在我的解决方案中所示。另一方面,如果你想要一个数组保存单个数据块,另一个数组保存指针,你必须像第一段代码的作者那样做。






我花了几分钟的时间来弄清楚三个变量的三维解法实际上是如何工作的,所以我给大家留下一个解释,谁会遇到这个线程。



一般的想法是有一个变量与实际数据和两个代理变量与一组指针,允许解决实际数据与 [] [] [] 符号。



C包含实际数据, $ c> [zDim * yDim * xDim] 。您可以通过 [z * xDim * yDim + y * xDim + x] (x,y,z) c $ c>。 [] [] [] 表示数据是通过切片(z)组织的,其中包含包含元素(x)的行(y)。



您构造数组B,其中包含指向所有行的指针,按切片顺序排列。所以B包含:(slice 0,row 0),(slice 0,row 1),...,(slice 0,row yDim-1),(slice 1,row 0),... 。



然后,构造数组A,其中包含指向数组B元素的指针,以使A的第z个元素指向(z * yDim) =第0个切片的第0行。最后,当你寻址数组A时,它的工作方式如下:




  • A [z] 包含数组B的元素的地址,其中包含指向第z个切片第0行的指针

  • A [z] [y]

  • 最后, A [z] [0] y] [x] 将我们移动x个元素,以便我们接收第z个切片的第y行的第x个元素。



现在应该很清楚,为什么你需要额外的变量,为什么它不能用单个变量来完成。



Bottomline使用这样的解决方案,它的巨大浪费内存。相反,通过 [z * xDim * yDim + y * xDim + x] 或使用jagged std :: vector s或 std :: array s。


I've gotten rid of the codes that do work as they were distracting. What I'm trying to do is allocate a single block of memory for a 3D array. I could simply just do the allocation as a jagged array, but it's more efficient to do a contiguous block.

Here's my current code snippet:

//Creating an array of proper size
//I first create an array of pointers
phi = new double**[xlength];
//I then create another array of pointers
phi[0] = new double*[xlength*ylength];
//At this point, I assume phi[0] and phi[0][0] have the same location. Is this not true?
phi[0][0] = new double[xlength*ylength*tlength];
//Now, I allocate the big block of data that will actually store my data
//I assume phi[0][0][0] has the same location as phi[0][0]. Is this right?
//Now, I'm trying to setup the pointers to match up in the single block of memory
    for (int i=0;i<xlength;i++)
    {
        for (int j=0;j<ylength;j++)
        {
            phi[i][j] = phi[0][0] + tlength*ylength*i + tlength*j;
        }
    }
//Does this not work? It feels as though it SHOULD

Adding back working code since answer depends on working code

double*** A = new double**[m];
double**  B = new double*[m*n];
double*   C = new double[m*n*o];
for (int i=0; i<m; i++) {
    for (int j=0; j<n; j++) {
        B[n*i+j] = C + (n*i+j)*o;
    }
    A[i] = B + n*i;
}
for (int i=0; i<m; i++) {
    for (int j=0; j<n; j++) {
        for (int k=0; k<o; k++) {
            A[i][j][k] = <my_value>;
        }
    }

Here's the solution guys!

Don't do 3D matrix, LOL! This is my most unpopular post ever!

Do a 1D matrix and follow the answer on this link C++ Segmentation Fault After When Trying to Write to Matrix

This is the important part of that link:

but then you cannot use the phi[i][j][k] notation, so you should

#define inphi(I,J,K) phi[(I)*xlength*ylength+(J)*xlength+(K)]

and write inphi(i,j,k) instead of phi[i][j][k]

解决方案

Remarks:

  • You do not free allocated memory by using delete[]. That's a very bad practice. You always should remember to free memory you allocated.

  • It is very, very uncomfortable to choose jagged arrays (arrays of arrays) for long term use. A lot easier solution is to allocate a single array:

    double * phi = new double[xlength * ylength];
    

    And then access (x, y)-th element as following:

    phy[y * xlength + x] = 20.0;
    

    The allocation takes less time, you have a lot less things to free (only the phi itself) and access time is more-less equally fast.

  • Consider using std::vector or std::array. Since you use C++ and not C, the natural way is to use these containers instead of raw arrays, they are a lot more managable and they care themselves to free their contents if allocated statically. In your case it would look like:

    #include <vector>
    
    (...)
    
    std::vector<std::vector<double> > phi;
    
    phi.resize(xlength);
    for (int x = 0; x < xlength; x++)
        phi[x].resize(ylength);
    

Solution:

Your solution won't work. The reason, why author of the original code uses three variables is, that one of them has to contain the actual data and two others serve as pointers to parts of the original data.

In your case, you try to keep both the data and pointers to parts of the data in the same array, what simply cannot work. If you want the [][][] notation, you have to allocate jagged arrays in nested loops, just as I've shown in my solution. On the other hand, if you want one array to keep single block of data and another to keep pointers, you'll have to do it as author of the first piece of code did.


It took me a few minutes of time to figure out, how the three-dimensional solution with three variables actually work, so I'll leave an explanation for everyone, who'll encounter this thread.

The general idea is to have one variable with actual data and two proxy variables with a set of pointers, which allows addressing the actual data with [][][] notation.

C contains the actual data, so it is of size [zDim * yDim * xDim]. You can access (x, y, z) element by addressing it by [z * xDim * yDim + y * xDim + x]. [][][] notation means, that the data is organized by slices (z), which contains rows (y), which contains elements(x).

You construct array B containing pointers to all rows, ordered by slice. So B contains: (slice 0, row 0), (slice 0, row 1), ..., (slice 0, row yDim - 1), (slice 1, row 0), ...

Then, you construct array A containing pointers to elements of array B, such that z-th element of A points to (z * yDim) = 0-th row of z-th slice. Finally, when you address the array A, it works like following:

  • A[z] contains address to element of array B containing pointer to 0th row of zth slice
  • A[z][y] moves this pointer, such that now we have actual pointer to 0-th element of y-th row of z-th slice.
  • Finally, A[z][y][x] shifts us by x elements, such that we receive x-th element of y-th row of z-th slice.

Now it should be clear, why you need additional variables and why it cannot be done with only single variable.

Bottomline: never use such solution, its a huge waste of memory. Instead, flatten your arrays and address by [z * xDim * yDim + y * xDim + x] or use jagged std::vectors or std::arrays.

这篇关于为什么顶层代码工作,底层代码不在c ++中进行动态矩阵分配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆