2

new を使用して動的に割り当てた 2 次元配列があります。

問題は、処理速度を上げるために、メモリを分割するのではなく、1 つの接続されたブロックとして割り当てたいことです。

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

次のように、1 つの大きなブロックを割り当てて適切に使用できます。

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

を使用する代わりに、使用newできます- でリリースする必要があることとでリリースする必要があることmallocを除いて、大きな違いはありません。newdeletemalloc()free()

UPDATE1 : 次のように「真の」2D 配列を作成できます。

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

最後にAとの両方を必ずリリースしてください。B

UPDATE2 :

一般的なリクエストにより、これは "真の" 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ます。いつものように、使用後は 3 つすべてを解放する必要があります。

これをより多くの次元に拡張することは、読者の演習として残されています。

于 2013-05-15T02:42:10.500 に答える
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 つの int と 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 に答える