2

我有一个使用 new 动态分配的二维数组。

问题是我想将内存分配为一个连接块而不是分开的块以提高处理速度。

有谁知道是否可以用 new 来做到这一点,还是我必须使用 malloc?

这是我的代码:

A = new double*[m];
    for (int i=0;i<m;i++)
    {
        A[i]= new double[n];
    }

此代码导致分段错误

phi = new double**[xlength];
phi[0] = new double*[xlength*ylength];
phi[0][0] = new double[xlength*ylength*tlength];
for (int i=0;i<xlength;i++)
{
    for (int j=0;j<ylength;j++)
    {
        phi[i][j] = phi[0][0] + (ylength*i+j)*tlength;
    }
    phi[i] = phi[0] + ylength*i;
}
4

3 回答 3

3

您可以分配一个大块并适当地使用它,如下所示:

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

可以不用 using new,而是使用malloc- 没有太大区别,只是new必须用 释放,deletemalloc()释放free()

UPDATE1:您可以按如下方式创建“真实”二维数组:

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

请务必同时释放AB最终释放。

更新2

根据普遍的要求,您可以通过以下方式创建“真正的” 3 维数组(尺寸为mx nx o):

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

这使用了 2 个相对较小的“索引”数组AB, 和数据数组C。像往常一样,这三个都应该在使用后释放。

将其扩展到更多维度作为练习留给读者。

于 2013-05-15T02:42:10.500 回答
0

没有什么malloc是你不能做的new(尽管反过来不成立)。但是,如果您已经在单独的块中分配了内存,则必须分配新的(连续的)内存才能获得连接的块(使用mallocnew)。您显示的代码分配m非连续n大小的块。要从中获取具有连续内存的数组,您需要

int MN = m*n;
B = new double[MN];
for (int i=0; i<MN; ++i)
   B[i] = A[ i/N ] [ i%N ];
于 2013-05-15T02:39:22.710 回答
0

好的,如果任务是维护单个内存块,但保持 [][] 解决它的方式,我会尝试使用类的一些技巧。第一个是内部代理:

class CoordProxy
{
private:
    int coordX;
    int arrayWidth;
    int * dataArray;

public:
    CoordProxy(int * newArray, int newArrayWidth, int newCoordX)
    {
        coordX = newCoordX;
        arrayWidth = newArrayWidth;
        dataArray = newArray;
    }

    int & operator [](int newCoordY)
    {
        return (dataArray[newCoordY * arrayWidth + coordX]);
    }
};

class CoordsWrapper
{
private:
    int * dataArray;
    int width;
    int height;

public:
    CoordsWrapper(int * newArray, int newWidth, int newHeight)
    {
        dataArray = newArray;
        width = newWidth;
        height = newHeight;
    }

    CoordProxy operator[] (int coordX)
    {
        return CoordProxy(dataArray, width, coordX);
    }
};

int main(int argc, char * argv[])
{
    int * a = new int[4 * 4];
    ZeroMemory(a, 4 * 4 * sizeof(int));

    CoordsWrapper w(a, 4, 4);

    w[0][0] = 10;
    w[0][1] = 20;
    w[3][3] = 30;

    std::for_each(&a[0], &a[4 * 4], [](int x) { printf("%d ", x); });

    delete[] a;
}

请注意,这不是时间效率高,但内存效率极高:比原始类多使用 4 个整数和 2 个指针。

还有更好更快的解决方案,但您必须放弃 [][] 表示法以支持 (,) 表示法:

class CoordsWrapper2
{
private:
    int * data;
    int width;
    int height;

public:
    CoordsWrapper2(int * newData, int newWidth, int newHeight)
    {
        data = newData;
        width = newWidth;
        height = newHeight;
    }

    inline int & Data(int x, int y)
    {
        return data[y * width + x];
    }
};

int main(int argc, char * argv[])
{
    int * a = new int[4 * 4];
    ZeroMemory(a, 4 * 4 * sizeof(int));

    CoordsWrapper2 w(a, 4, 4);

    w.Data(0, 0) = 10;
    w.Data(0, 1) = 20;
    w.Data(3, 3) = 30;

    std::for_each(&a[0], &a[4 * 4], [](int x) { printf("%d ", x); });

    delete[] a;
}

注意 inline 指令。它建议编译器替换实际源代码的方法调用,这使其速度更快。此解决方案的内存效率更高,并且与经典索引相比,时间效率略低或相同。

于 2013-05-15T17:45:10.373 回答