Allokieren von 2D-Array in Funktion



  • Hallo,

    ich bin gerade am verzweifeln mit einem C++-Code. Ich bin mir nicht mehr sicher, ob ich die Allokation von meinen Arrays richtig mache.
    Ich möchte innerhalb einer Funktion ein 2D-Array allokieren.
    Die Frage: Ist mein Codeausschnitt richtig? Bzw. mache ich die Allokierung richtig.
    Und vorallem greife ich in main richtig auf die Elemente des Arrays zu?

    #include <iostream>
    
    using namespace std;
    
    int allocate(int ***, int*, int*);
    
    int main()
    {
      int** array;
      int errFlag;
      int ii;
      int jj;
      int firstDim;
      int secondDim;
    
      firstDim = 50;
      secondDim = 100;
      errFlag = allocate(&array, &firstDim, &secondDim);
    
      for (ii=0;ii<firstDim;ii++) {
        for (jj=0;jj<secondDim;jj++) {
          cout << "array[" << ii << "][" << jj << "]=" << (array)[ii][jj] << endl;;
        }
      }
    
    }
    int allocate(int *** array, int* firstDim, int* secondDim) {
      int ii;
      int jj;
      int counter;
    
      counter = 0;
      *array = new int*[*firstDim];
      for (ii=0;ii<*secondDim;ii++) {
        (*array)[ii] = new int[*secondDim];
      }
    
      for (ii=0;ii<*firstDim;ii++) {
        for (jj=0;jj<*secondDim;jj++) {
          (*array)[ii][jj] = counter;
          counter++;
        }
      }
      return 0;
    }
    

    Bin neu in der Programmiersprache c++. Wäre super, wenn einer kurz sagen könnte obs richtig oder falsch ist.

    Vielen Dank.



  • AAAAAAAAAAAAAAAAAAAAAAAAAAAAAH! *schreiend wegrenn*

    Nein, nein, nein, so macht man so was in C++ doch nicht. In C vielleicht, aber doch nicht in C++.

    Einfache Variante:

    #include <vector>
    
    ...
    
    std::vector<std::vector<int> > vec(50, std::vector<int>(100));
    

    ...erstellt einen Vektor von 50 Vektoren von jeweils 100 ints, und du musst dich nicht mal ums Aufräumen kümmern. Welches du übrigens vergessen hattest.

    Generell ist es in C++ eine schlechte Idee, mit (besitzenden) nackten Zeigern zu arbeiten, weil solcher Code ausgesprochen schwer exceptionsicher zu kriegen ist (und auch sonst mehr Arbeit macht). Wann immer eine Ressource angefordert wird, sollte sie sofort an ein Objekt gekettet werden, das sich um die Aufräumarbeit kümmert, wenn es sein Scope verlässt -- in diesem Fall übernehmen das vec und die von vec verwalteten Untervektoren.

    Wo hast du diesen Drei-Sterne-Unfug überhaupt her? Auf den Galileo-Verlag reingefallen?



  • Das hatte ich mir selber gebaut. Habe erst vor kurzem mit C++ angefangen, daher noch wenig Erfahrung damit.
    Werds mit dem Vektor mal versuchen.
    Danke für die Antwort.



  • Dein Ansatz ist schon mal nicht schlecht. Kurzer Hinweis: die Zählvariablen in den Schleifen (also ii bzw. jj) solltest du erst bei der Initialisierung anlegen, wenn sie nach der Schleife in der Funktion nicht weiter leben sollten (so wie's hier der Fall ist).

    Dein C/C++-Hybrid sollte eher so aussehen (nicht getestet), aber wie gesagt, das ist alles andere als schön oder sicher:

    #include <iostream>
    
    //using namespace std;    Wegen ein paar couts sollte man das nie global angeben
    
    int allocate(int *** dynArr, unsigned firstDim, unsigned secondDim);
    
    int main()
    {
      int ** dynArr;
    
      unsigned firstDim = 50;
      unsigned secondDim = 100;
      int errFlag = allocate(&dynArr, firstDim, secondDim);
    
      for (unsigned ii = 0; ii < firstDim; ii++)
        for (unsigned jj = 0; jj < secondDim; jj++)
          std::cout << "dynArr[" << ii << "][" << jj << "]=" << dynArr[ii][jj] << std::endl;
    
      //Aufräumen:
      for (unsigned i = 0; i < firstDim; i++)
        delete [] (dynArr[i]);
      delete [] dynArr;
    }
    
    int allocate(int *** dynArr, unsigned firstDim, unsigned secondDim) {
    
      *dynArr = new int*[firstDim];
      for (unsigned ii = 0; ii < firstDim; ii++)   //hier hattest du den gültigen Speicherbereich verlassen
        (*dynArr)[ii] = new int[secondDim];
    
      for (unsigned ii = 0; ii < firstDim; ii++)
    	  for (unsigned jj=0; jj < secondDim; jj++) 
          (*dynArr)[ii][jj] = secondDim * ii + jj; //counter;
    
      return 0;   //Überflüssig, wenn keine anderen Fälle abgefangen werden
    }
    


  • [Rewind] schrieb:

    Dein C/C++-Hybrid sollte eher so aussehen (nicht getestet), aber wie gesagt, das ist alles andere als schön oder sicher:

    Si tacuisses...

    Oder: Was ist denn an dem Beispiel besser als am Original?



  • Wenn du keinen Unterschied siehst, dann kann ich dir nicht helfen.



  • Oft macht es auch Sinn ein 2 dimensionales Array als 1 dimensionales anzulegen.

    Statt arr[i][j] kann man dann zB per arr[size*i+j] darauf zugreifen. Das erleichtert die Verwaltung oft enorm.



  • [Rewind] schrieb:

    int allocate(int ** array, unsigned firstDim, unsigned secondDim) {
     
      array = new int*[firstDim];
    

    Das ist nicht dein Ernst, oder?



  • for (int i = 0; i < firstDim; i++)
      delete [] array[i];
    delete [] array;
    

    Was ist denn der Vorteil wenn ich die Variablen der Schleifen in der Schleife direkt deklariere? Bin Fortran Muttersprachler und kenne das daher nicht anders.
    Gibt es da einen wesentlichen Vorteil gegenüber der Deklaration am Anfang der Funktion?



  • Variablen dort zu deklarieren wo man sie benötigt macht es übersichtlicher. Auch ist in diesem Fall "i" nur innerhalb der Schleife gültig und kann somit zB in einer zweiten Schleife erneut verwendet werden ohne Gefahr zu laufen aus Versehen den Wert der vorherigen Verwendung zu übernehmen.



  • Ok, das hat aber dann nur Vorteile hinsichtlich der Übersichtlichkeit. Performancevorteile erhalte ich dadurch nicht?



  • Reicht das nicht?



  • maxinagl schrieb:

    Ok, das hat aber dann nur Vorteile hinsichtlich der Übersichtlichkeit. Performancevorteile erhalte ich dadurch nicht?

    Performance - nein. Aber lies dir nochmal den Beitrag von Fellhuhn genauer durch. Im Prinzip bedeutet bessere Übersichtlichkeit gleich eine niedrigere Wahrscheinlichkeit, dass du Fehler machst, und einen geringeren Aufwand bei der Fehlersuche. Kennst du noch den Spaghetti-Code mit goto's..? Dann weißt du, was ich meine.


Anmelden zum Antworten