2016-05-13 3 views
0

Ich habe eine Simulation auf einem 3D-Ising Gittern von Einsen und Minusfehler auf einem 3D es vertreten zu implementieren wäre sehr nützlich, wenn die Größe zur Laufzeit bestimmt werden kann (für mehr Flexibilität). Da es viele Zugriffe auf die Einträge der Speicherzuordnung so lokal wie möglich sein sollte. Wenn etwas gefunden, für einen 2D-Array: Copy 2D array using memcpy?:cpp 3d dinamic Erstellung von 3D-Arrays von einem einzigen Speicher, der aus Block

GridUnit** newGrid; 
newGrid = new GridUnit*[width]; 
newGrid[0] = new GridUnit[width * height]; 
for (int i = 1; i < width; i++) 
    newGrid[i] = newGrid[i-1] + height; 

Ausplanung wird einfacher:

delete[] newGrid[0]; 
delete[] newGrid; 

und meine Bewertung ist zu niedrig, um den Beitrag zu kommentieren oder zu beantworten. Ich habe im Grunde zwei Fragen über den Code: 1.warum ist das Gitter als Zeiger auf Arrays von length = width definiert und die Iteration findet statt über einen Index bis zur Breite Verschiebung der Adresse nach Höhe? verkompliziert das nicht den Zeilen- und Spaltenindex? 2. Soll ich dann eine Reihe von length=width mit Zeigern auf Arrays von length=height*depth erklären, die in dem folgenden Code führen würden:

int*** new3dGrid(int width, int height, int depth){ 
    int*** newGrid; 
    newGrid = new int**[height*depth]; 
    newGrid[0][0] = new int[width * height * depth]; 
    for (int i = 1; i < width; i++){ 
    newGrid[i] = newGrid[i-1] + height*depth; 
    for (int j=1;j<height;j++){ 
     newGrid[i][j]=newGrid[i][j-1]+depth; 
    } 
    } 
    return newGrid; 
} 
+0

Der 3-D-Fall ist in meiner Antwort hier enthalten: https://StackOverflow.com/a/29582795/103167 –

Antwort

0

Zu allererst: Ich STARK schlage vor, Sie zu verwenden, wenn möglich, Standard-C++ Behälter; im 2D-Fall (Achtung: nicht getestet)

Ich empfehle dies vor allem, wenn das Beispiel, das Sie erwähnen, nicht absolut klar ist.

Überlegen Sie, ob Sie an der Position zugreifen i, j

gu2d[i][j] = GridUnit(); 

wo aus Versehen j Wert ist height; ohne es zu merken, ändern Sie gu2d[i+1][0]. Wenn gu2d ein Vektor von Vektoren ist, mit gu2d.at(i).at(j) erhalten Sie gebundene Prüfung und eine schöne Ausnahme.

  1. Deshalb wird das Gitter als Zeiger auf Arrays von Länge = Breite definiert, und die Iteration erfolgt über einen Index, indem die Adresse Höhe Breite Verschiebung Steigen?

Sie können eine 2D-Matrix als ein Array von Reihen von Zellen width sehen, wo jede Zeile von Zellen height ist.

So hat der erste Zeiger (newGrid) Länge width, weil es width Zeilen referenziert.

Jede Zeile hat eine Länge height, so dass die durch widthnewGrid referenzierten Werte werden getrennt (verschoben) durch einen Abstand von height (in pointer metric).

Ich denke, man kann klarer sein, wenn Sie die erste Antwort auf diese Frage lesen

How do I declare a 2d array in C++ using new?

  1. Soll ich dann ein Array mit einer Länge = Breite deklarieren mit Zeiger auf Arrays mit einer Länge = Höhe * Tiefe, die in dem folgenden Code

ich bin kein Englisch Muttersprachler, aber es scheint mir, würden t Hast du eine unglückliche Reihenfolge der Namen gewählt? Ich nehme an, Sie sollten depthvorwidth verwenden.

Aber Ihre tatsächlichen Namen mit (width ist die Dimension des ersten Index, height des zweiten, depth des dritten) ...

Genau.

sollte Ihr Code ändern

newGrid = new int**[height*depth]; 

Breite

newGrid = new int**[width]; 

Im 3D-Fall können Sie newGrid als (mit Ihrem wählen einen Namen) ein Array von width 2D-Matrix sehen, wo die 2D-Matrix sind Arrays von height Zeilen von depth Zellen. Jede 2D-Matrix hat also die Größe heigth * depth.

Vorsicht: Speicher mit

delete newGrid[0][0]; 
delete newGrid; 

ps zu löschen: sorry für mein schlechtes Englisch

--- EDIT ---

Leider ich keinen Punkt gesehen habe das ist wichtig für Ihre Hypotesis von new3dGrid: Sie sollten drei Zeiger, nicht zwei: newGrid, wie int***, fo r Größe width; newGrid[0], wie int** für die Größe width * height; newGrid[0][0], wie int*, für die Größe width * height * depth. Die drei Arten von Zeigern benötigen unterschiedliche zugewiesene Bereiche.

Ich schlage die verschiedene Template-Version vor (Achtung: nicht getestet) [korrigiert von Ben Voigt; Dank!]

template <typename T> 
T*** new3dGrid (unsigned height, unsigned width, unsigned depth) 
{ 
    T*** newGrid; 

    newGrid  = new T**[width]; 
    newGrid[0] = new T*[width * height]; 
    newGrid[0][0] = new T[width * height * depth]; 

    for (unsigned i = 0U ; i < width ; ++i) 
    { 
     if (i > 0U) 
     { 
     newGrid[i] = newGrid[i-1U] + height; 
     newGrid[i][0] = newGrid[i-1U][0] + height * depth; 
     } 

     for (unsigned j = 1U ; i < height ; ++j) 
     newGrid[i][j] = newGrid[i][j-1U] + depth; 
    } 

    return newGrid; 
} 

und Sie sollten drei Zeiger

delete newGrid[0][0]; 
delete newGrid[0]; 
delete newGrid; 

leider löschen.

+0

Diese Zeile ist ein Fehler: 'newGrid [i] = newGrid [i-1U] + Höhe * Tiefe; ', sehen Sie bitte meine Antwort unter https://stackoverflow.com/a/29582795/103167 –

+0

@BenVoigt - D'oh! Du hast recht!Ich habe den Code für zwei verschiedene Ebenen gemischt und vergessen, auf Stufe 0 zu initialisieren. Vielen Dank. Bitte, können Sie überprüfen, ob ich meinen Code richtig geändert habe (dh wenn ich Ihren Code korrekt kopiert habe)? – max66

+0

du hast ein 'für' wenn du' if' meintest, sonst sieht es gut aus –