webentwicklung-frage-antwort-db.com.de

Dynamisches zweidimensionales Array mit Zeiger zu Zeiger

Erster Timer auf dieser Website, also hier gehts ..

Ich bin ein Neuling in C++ und arbeite gerade durch das Buch "Datenstrukturen mit C++ 2nd ed, von D.S. Malik". 

In dem Buch bietet Malik zwei Möglichkeiten, ein dynamisches zweidimensionales Array zu erstellen. In der ersten Methode deklarieren Sie eine Variable als ein Array von Zeigern, wobei jeder Zeiger vom Typ Integer ist. Ex.

int *board[4];

..und verwenden Sie dann eine for-Schleife, um die 'Spalten' zu erstellen, während Sie das Array von Zeigern als 'Zeilen' verwenden.

Bei der zweiten Methode verwenden Sie einen Zeiger auf einen Zeiger.

int **board;
board = new int* [10]; 

usw.

Meine Frage lautet: Welches ist die bessere Methode? Die Methode ** ist für mich einfacher zu visualisieren, aber die erste Methode kann auf ähnliche Weise verwendet werden. Beide Wege können verwendet werden, um dynamische 2-D-Arrays zu erstellen. 

Edit: War mit dem obigen Beitrag nicht klar genug. Hier ist ein Code, den ich ausprobiert habe:

int row, col;

cout << "Enter row size:";
cin >> row;
cout << "\ncol:";
cin >> col;

int *p_board[row];
for (int i=0; i < row; i++)
    p_board[i] = new int[col];

for (int i=0; i < row; i++)
{
    for (int j=0; j < col; j++)
    {
        p_board[i][j] = j;
        cout << p_board[i][j] << " ";
    }
    cout << endl;
}
cout << endl << endl;

int **p_p_board;
p_p_board = new int* [row];
for (int i=0; i < row; i++)
    p_p_board[i] = new int[col];

for (int i=0; i < row; i++)
{
    for (int j=0; j < col; j++)
    {
        p_p_board[i][j] = j;
        cout << p_p_board[i][j] << " ";
    }
    cout << endl;
}
20
user2280041

Die erste Methode kann nicht zum Erstellen von dynamischen 2D-Arrays verwendet werden, da:

int *board[4];

sie haben inton stack im Wesentlichen ein Array mit 4 Zeigern zugewiesen. Wenn Sie jetzt jeden dieser 4 Zeiger mit einem dynamischen Array füllen, gehen Sie folgendermaßen vor:

for (int i = 0; i < 4; ++i) {
  board[i] = new int[10];
}

am Ende steht ein 2D-Array mit statisch Zeilenanzahl (in diesem Fall 4) und dynamisch Spaltenanzahl (in diesem Fall 10). Es ist also nicht vollständig dynamisch, da Sie beim Zuweisen eines Arrays auf dem Stack sollte eine konstante Größe angeben, dh bekannt unter kompilieren) -time. Dynamisch Array heißt Dynamisch, da seine Größe nicht zum Zeitpunkt Kompilierzeit bekannt sein muss, sondern durch eine Variable in - bestimmt werden kann. Laufzeit.

Wieder einmal, wenn Sie dies tun:

int *board[4];

oder:

const int x = 4; // <--- `const` qualifier is absolutely needed in this case!
int *board[x];

sie geben eine Konstante an, die um Kompilierungszeit (in diesem Fall 4 oder x) bekannt ist, damit der Compiler jetzt vorab reservieren diesen Speicher für Ihr Array und Wenn Ihr Programm in den Speicher geladen wird, verfügt es bereits über diese Speicherkapazität für das Array board. Deshalb heißt es statisch, dh, weil die Größe schwer) ist. codiert und nicht dynamisch änderbar (zur Laufzeit).

Auf der anderen Seite, wenn Sie tun:

int **board;
board = new int*[10];

oder:

int x = 10; // <--- Notice that it does not have to be `const` anymore!
int **board;
board = new int*[x];

der Compiler weiß nicht, wie viel Speicher das Array board benötigt, und daher vorab reservieren nichts. Wenn Sie jedoch Ihr Programm starten, wird die Größe des Arrays durch den Wert der Variablen x (zur Laufzeit) bestimmt, und der entsprechende Speicherplatz für das Array board wird auf dem sogenannten heap - Der Speicherbereich, in dem alle auf Ihrem Computer ausgeführten Programme Speicher zuordnen können vorher unbekannt (zur Kompilierungszeit) Der Speicher für den persönlichen Gebrauch.

Um ein dynamisches 2D-Array zu erstellen, müssen Sie daher die zweite Methode anwenden:

int **board;
board = new int*[10]; // dynamic array (size 10) of pointers to int

for (int i = 0; i < 10; ++i) {
  board[i] = new int[10];
  // each i-th pointer is now pointing to dynamic array (size 10) of actual int values
}

Wir haben gerade ein quadratisches 2D-Array mit 10 x 10 Dimensionen erstellt. Um es zu durchlaufen und mit tatsächlichen Werten zu füllen, zum Beispiel 1, könnten wir verschachtelte Schleifen verwenden:

for (int i = 0; i < 10; ++i) {   // for each row
  for (int j = 0; j < 10; ++j) { // for each column
    board[i][j] = 1;
  }
}
44

Was Sie für die zweite Methode beschreiben, gibt Ihnen nur ein 1D-Array:

int *board = new int[10];

Dies weist nur ein Array mit 10 Elementen zu. Vielleicht meintest du so etwas:

int **board = new int*[4];
for (int i = 0; i < 4; i++) {
  board[i] = new int[10];
}

In diesem Fall weisen wir 4 int*s zu und machen dann jeden auf ein dynamisch zugewiesenes Array von 10 ints.

Jetzt vergleichen wir das mit int* board[4];. Der Hauptunterschied besteht darin, dass bei Verwendung eines solchen Arrays die Anzahl der "Zeilen" zum Zeitpunkt der Kompilierung bekannt sein muss. Das liegt daran, dass Arrays feste Größen für die Kompilierungszeit haben müssen. Sie haben möglicherweise auch ein Problem, wenn Sie dieses Array von int*s möglicherweise zurückgeben möchten, da das Array am Ende seines Bereichs zerstört wird.

Die Methode, bei der sowohl die Zeilen als auch die Spalten dynamisch zugewiesen werden, erfordert kompliziertere Maßnahmen, um Speicherverluste zu vermeiden. Sie müssen die Erinnerung wie folgt freigeben:

for (int i = 0; i < 4; i++) {
  delete[] board[i];
}
delete[] board;

Ich muss empfehlen, stattdessen einen Standardbehälter zu verwenden. Sie können einen std::array<int, std::array<int, 10> 4> oder vielleicht einen std::vector<std::vector<int>> verwenden, den Sie auf die entsprechende Größe initialisieren.

5

In beiden Fällen kann Ihre innere Dimension dynamisch angegeben werden (d. H. Einer Variablen entnommen werden), die Differenz liegt jedoch in der äußeren Dimension.

Diese Frage entspricht im Wesentlichen dem Folgenden:

Ist int* x = new int[4]; "besser" als int x[4]?

Die Antwort lautet: " nein , sofern Sie diese Array-Dimension nicht dynamisch auswählen müssen."

Dieser Code funktioniert gut mit sehr wenigen Anforderungen an externe Bibliotheken und zeigt eine grundlegende Verwendung von int **array.

Diese Antwort zeigt, dass jedes - Array eine dynamische Größe hat und wie ein Blatt-Array mit dynamischer Größe dem Zweig mit dynamischer Größe zugewiesen wird.

Dieses Programm übernimmt Argumente von STDIN im folgenden Format:

2 2   
3 1 5 4
5 1 2 8 9 3
0 1
1 3

Code für das Programm unten ...

#include <iostream>

int main()
{
    int **array_of_arrays;

    int num_arrays, num_queries;
    num_arrays = num_queries = 0;
    std::cin >> num_arrays >> num_queries;
    //std::cout << num_arrays << " " << num_queries;

    //Process the Arrays
    array_of_arrays = new int*[num_arrays];
    int size_current_array = 0;

    for (int i = 0; i < num_arrays; i++)
    {
        std::cin >> size_current_array;
        int *tmp_array = new int[size_current_array];
        for (int j = 0; j < size_current_array; j++)
        {
            int tmp = 0;
            std::cin >> tmp;
            tmp_array[j] = tmp;
        }
        array_of_arrays[i] = tmp_array;
    }


    //Process the Queries
    int x, y;
    x = y = 0;
    for (int q = 0; q < num_queries; q++)
    {
        std::cin >> x >> y;
        //std::cout << "Current x & y: " << x << ", " << y << "\n";
        std::cout << array_of_arrays[x][y] << "\n";
    }

    return 0;
}

Es ist eine sehr einfache Implementierung von int main und basiert ausschließlich auf std::cin und std::cout. Barebones, aber gut genug, um zu zeigen, wie mit einfachen mehrdimensionalen Arrays gearbeitet wird.

0
Andrew