643 Stimmen

Wie deklariere ich ein 2d-Array in C++ mit new?

Wie deklariere ich ein 2d-Array mit new?

Bei einer "normalen" Anordnung würde ich das tun:

int* ary = new int[Size]

mais

int** ary = new int[sizeY][sizeX]

a) nicht funktioniert/kompiliert und b) nichts bewirkt:

int ary[sizeY][sizeX] 

tut.

74 Stimmen

Es funktioniert nur, wenn sizeX konstant ist: int(*ary)[sizeX] = new int[sizeY][sizeX]; Das ist der richtige Weg, um einen int[sizeY][sizeX] zu erstellen, bei dem der gesamte Speicher zusammenhängend ist. (Ich glaube nicht, dass dies eine Antwort wert ist, da wahrscheinlich Ihre sizeX nicht konstant ist

36 Stimmen

Ich kann nicht glauben, dass all die Dutzende von Antworten unten sind todos falsch und beantwortet die Frage nicht, und dennoch werden sie alle hochgestuft. Der obige Kommentar von Johanes Shaub ist die einzig richtige Antwort auf die Frage . Ein 2D-Array und ein Array mit Zeigern auf ein Array sind zwei völlig verschiedene Dinge, die offenbar jeder verwechselt.

8 Stimmen

@JohannesSchaub-litb: Das ist nicht 100%ig richtig. Sicherlich funktioniert es in diesem Fall, aber es gibt eine Methode, mit der es funktioniert, wenn alle Dimensionen variieren, siehe stackoverflow.com/a/29375830/103167

16voto

etham Punkte 2580

Wie weist man ein zusammenhängendes mehrdimensionales Array in GNU C++ zu? Es gibt eine GNU-Erweiterung, mit der die "Standard"-Syntax funktioniert.

Das Problem scheint vom neuen Betreiber [] zu kommen. Stellen Sie sicher, dass Sie stattdessen den Operator new verwenden:

double (* in)[n][n] = new (double[m][n][n]);  // GNU extension

Und das ist alles: Sie erhalten ein C-kompatibles mehrdimensionales Array...

13voto

Robert S. Barnes Punkte 38141

typedef ist dein Freund

Nachdem ich mir viele der anderen Antworten angesehen habe, bin ich zu dem Schluss gekommen, dass eine tiefergehende Erklärung angebracht ist, da viele der anderen Antworten entweder unter Leistungsproblemen leiden oder Sie dazu zwingen, eine ungewöhnliche oder umständliche Syntax zu verwenden, um das Array zu deklarieren oder auf die Arrayelemente zuzugreifen (oder all das).

Zunächst einmal setzt diese Antwort voraus, dass Sie die Abmessungen des Arrays zur Kompilierungszeit kennen. Wenn dies der Fall ist, dann ist dies die beste Lösung, da sie sowohl die beste Leistung und ermöglicht Ihnen die Verwendung von Standard-Array-Syntax für den Zugriff auf die Array-Elemente .

Der Grund für die beste Leistung liegt darin, dass alle Arrays als zusammenhängende Speicherblöcke zugewiesen werden, was bedeutet, dass Sie wahrscheinlich weniger Seitenfehler und eine bessere räumliche Lokalisierung haben. Die Zuweisung in einer Schleife kann dazu führen, dass die einzelnen Arrays auf mehreren nicht zusammenhängenden Seiten im virtuellen Speicher verstreut sind, da die Zuweisungsschleife (möglicherweise mehrmals) von anderen Threads oder Prozessen unterbrochen werden könnte oder einfach aufgrund des Ermessens des Zuweisers, der kleine, leere Speicherblöcke auffüllt, die ihm zufällig zur Verfügung stehen.

Weitere Vorteile sind eine einfache Deklarationssyntax und eine Standard-Array-Zugriffssyntax.

In C++ mit new:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

typedef double (array5k_t)[5000];

array5k_t *array5k = new array5k_t[5000];

array5k[4999][4999] = 10;
printf("array5k[4999][4999] == %f\n", array5k[4999][4999]);

return 0;
}

Oder C-Stil mit calloc:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

typedef double (*array5k_t)[5000];

array5k_t array5k = calloc(5000, sizeof(double)*5000);

array5k[4999][4999] = 10;
printf("array5k[4999][4999] == %f\n", array5k[4999][4999]);

return 0;
}

9voto

Zargles Punkte 329

Der Zweck dieser Antwort ist nicht, etwas Neues hinzuzufügen, was die anderen nicht schon abdecken, sondern die Antwort von @Kevin Loney zu erweitern.

Sie könnten die leichtgewichtige Erklärung verwenden:

int *ary = new int[SizeX*SizeY]

und die Zugriffssyntax wird sein:

ary[i*SizeY+j]     // ary[i][j]

aber das ist für die meisten umständlich und kann zu Verwirrung führen. Sie können also ein Makro wie folgt definieren:

#define ary(i, j)   ary[(i)*SizeY + (j)]

Jetzt können Sie auf das Array mit einer sehr ähnlichen Syntax zugreifen ary(i, j) // means ary[i][j] . Dies hat den Vorteil, dass es einfach und schön ist, und gleichzeitig ist die Verwendung von Ausdrücken anstelle der Indizes auch einfacher und weniger verwirrend.

Um z. B. auf ary[2+5][3+8] zuzugreifen, können Sie schreiben ary(2+5, 3+8) anstelle des komplex aussehenden ary[(2+5)*SizeY + (3+8)] d.h. es spart Klammern und verbessert die Lesbarkeit.

Vorbehalte:

  • Obwohl die Syntax sehr ähnlich ist, ist sie NICHT dieselbe.
  • Für den Fall, dass Sie das Array an andere Funktionen übergeben, SizeY muss mit demselben Namen übergeben werden (oder stattdessen als globale Variable deklariert werden).

Wenn Sie das Array in mehreren Funktionen verwenden müssen, können Sie SizeY auch als weiteren Parameter in die Makrodefinition aufnehmen, etwa so:

#define ary(i, j, SizeY)  ary[(i)*(SizeY)+(j)]

Sie haben die Idee. Natürlich wird dies zu lang, um nützlich zu sein, aber es kann immer noch die Verwechslung von + und * verhindern.

Dies ist nicht unbedingt empfehlenswert und wird von den meisten erfahrenen Benutzern als schlechte Praxis verurteilt werden, aber ich konnte nicht widerstehen, es wegen seiner Eleganz zu teilen.

編集する。
Wenn Sie eine portable Lösung wünschen, die für eine beliebige Anzahl von Arrays funktioniert, können Sie diese Syntax verwenden:

#define access(ar, i, j, SizeY) ar[(i)*(SizeY)+(j)]

und dann können Sie ein beliebiges Array mit beliebiger Größe unter Verwendung der Zugriffssyntax an den Aufruf weitergeben:

access(ary, i, j, SizeY)      // ary[i][j]

P.S.: Ich habe diese getestet, und die gleiche Syntax funktioniert (sowohl als lvalue als auch als rvalue) auf g++14 und g++11 Compilern.

7voto

stanigator Punkte 10458

Versuchen Sie dies zu tun:

int **ary = new int* [sizeY];
for (int i = 0; i < sizeY; i++)
    ary[i] = new int[sizeX];

2voto

emarazz Punkte 29

Hier habe ich zwei Möglichkeiten. Die erste zeigt das Konzept eines Arrays von Arrays oder eines Zeigers von Zeigern. Ich bevorzuge die zweite Variante, weil die Adressen zusammenhängend sind, wie Sie im Bild sehen können.

enter image description here

#include <iostream>

using namespace std;

int main(){

    int **arr_01,**arr_02,i,j,rows=4,cols=5;

    //Implementation 1
    arr_01=new int*[rows];

    for(int i=0;i<rows;i++)
        arr_01[i]=new int[cols];

    for(i=0;i<rows;i++){
        for(j=0;j<cols;j++)
            cout << arr_01[i]+j << " " ;
        cout << endl;
    }

    for(int i=0;i<rows;i++)
        delete[] arr_01[i];
    delete[] arr_01;

    cout << endl;
    //Implementation 2
    arr_02=new int*[rows];
    arr_02[0]=new int[rows*cols];
    for(int i=1;i<rows;i++)
        arr_02[i]=arr_02[0]+cols*i;

    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++)
            cout << arr_02[i]+j << " " ;
        cout << endl;
    }

    delete[] arr_02[0];
    delete[] arr_02;

    return 0;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X