Deklaration eines zweidimensionalen Arrays mit new



  • Ich habe versucht, ein zweidimensionales Array zu deklarieren, aber es ist wohl falsch:

    int **array = new int[3][5];
    

    Wie macht man's richtig?

    Und was das Löschen betrifft: Würde delete[] array; oder muss man irgendwas von wegen delete[][] array; machen?



  • Dynamische, zweidimensionale Arrays gibts nicht, man nimmt ein eindimensionales und berechnet dann jedesmal den Index mit y*width+x . Dann reicht auch ein stinknormales delete[] .
    Oder man verwendet Boost.MutiArray.



  • Hallo,

    Schaut mal in die FAQ
    http://www.c-plusplus.net/forum/39489



  • Wenn beide Dimensionen bekannt sind, reicht

    int a[3][5];
    

    Ist nur die innere bekannt, ginge

    int (*a)[5] = new int[dim_x][5];
    
    // ...
    
    delete[] a;
    

    Ist keine bekannt, gibt es eine Reihe von Möglichkeiten. Boost hat eine Multi-Array-Bibliothek, die einen Blick wert sein dürfte, ansonsten wäre etwas in dieser Art eine einfache Möglichkeit:

    #include <vector>
    
    template<typename T>
    class array2d {
    public:
      typedef T                 value_type;
      typedef value_type       *pointer;
      typedef value_type const *const_pointer;
      typedef std::size_t       size_type;
    
      array2d(size_type dim_x, size_type dim_y)
        : dim_y_(dim_y),
          data_(dim_x * dim_y) { }
    
            pointer operator[](size_type x)       { return &data_[x * dim_y_]; }
      const_pointer operator[](size_type x) const { return &data_[x * dim_y_]; }
    
    private:
      size_type               dim_y_;
      std::vector<value_type> data_;
    };
    
    // ...
    
    array2d<int> a(x, y);
    
    // keine Freigabe notwendig (RAII)
    


  • seldon schrieb:

    ansonsten wäre etwas in dieser Art eine einfache Möglichkeit:

    pointer operator[](size_type x)       { return &data_[x * dim_y_]; }
    const_pointer operator[](size_type x) const { return &data_[x * dim_y_]; }
    

    Igitt!

    Wenn dann lieber sowas:

    typedef T                 value_type;
    typedef value_type       &reference;
    typedef value_type const &const_reference;
    typedef std::size_t       size_type;
    
          reference operator()(size_type x, size_type y)       { return data_[y*dim_x_+x]; }
    const_reference operator()(size_type x, size_type y) const { return data_[y*dim_x_+x]; }
    

    Siehe: http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.11



  • ...der Text hinter dem Link besagt, dass der operator()-Ansatz für zerstreute Matrizen sinnvoller ist. Das ist zwar richtig, hat aber für diesen Anwendungsfall keinerlei Bedeutung.



  • Hier ein kleines Beispiel für ein 2D Array:

    //	Dynamic array 2D
    #include <iostream>
    #include <conio.h>
    using namespace std;
    double ** make2dFeld(int ,int );
    void init2dFeld(double **,int,int);
    void show2dFeld(double **,int,int);
    void delete2dFeld(double **,int); 
    int main()
    {
      int     n,m,i,j;
      double  **b;          
    
      cout << "  Eingabe Zeilen  n : ";  cin >> n;
      cout << "  Eingabe Spalten m : ";  cin >> m;
    
      b =  make2dFeld(n,m);      
    
      init2dFeld(b,n,m);        
      show2dFeld(b,n,m);        
      delete2dFeld(b,n);        
    
      getch();
      return 0;
    
    }
    //----------------------------------------------------------------------
    double ** make2dFeld(int z,int s)
    {
        double **b;
        b = new (double* [z]);     
        for (int i = 0; i < z; i++)
        {
            b[i] = new double[s];    
        }
        return b;
    }
    //----------------------------------------------------------------------
    void init2dFeld(double **b,int z,int s)
    {
        for (int i = 0; i < z; i++ )   
        {
            for (int j = 0; j < s; j++)
            {
                b[i][j] = (i+1)*(j+1);
            }
       }
    }
    //----------------------------------------------------------------------
    void show2dFeld(double **b,int z,int s)
    {
        for (int i = 0; i < z; i++ )    
        {
            for (int j = 0; j < s; j++)
            {
                cout<<b[i][j]<<',';
            }
            cout<<endl;
       }
    }
    //----------------------------------------------------------------------
    void delete2dFeld(double **b,int z)
    {
        for (int i=0; i<z; i++)
        {
            delete []  b[i];            
        }
        delete [] b;  
    }
    


  • make2dFeld
    init2dFeld
    show2dFeld
    delete2dFeld

    Entweder Deutsch oder Englisch. Entscheide dich...



  • Denglisch schrieb:

    make2dFeld
    init2dFeld
    show2dFeld
    delete2dFeld

    Entweder Deutsch oder Englisch. Entscheide dich...

    Troll wo anders!



  • Cybertec schrieb:

    Troll wo anders!

    Nur nicht gleich persönlich nehmen. Auch wenn es kein entscheidender Punkt ist: Dieses Bezeichnergemisch finde ich auch grauenhaft.

    Aber um noch wichtigere Dinge zu nennen: Dein Code ist ziemlicher C-Style. Der Benutzer wird zu manueller Speicherverwaltung gezwungen. Er muss sich die Arraygrösse jeweils separat merken und hat beim Zugriff null Sicherheit. In einer Klasse gekapselt könnte man diese Probleme stark dezimieren.

    Davon abgesehen ist es relativ ineffizient, viele kleine Allokationen für die Unter-Arrays zu haben (es sei denn, das Array ist wirklich gross). Wahrscheinlich wäre ein 1D-Array mit interner Indexumrechnung angebrachter.

    Wenn kein wesentlicher Grund dagegen spricht, würde ich ohnehin getesteten Code wiederverwenden. Also boost::multi_array oder mindestens std::vector .



  • Der Code war noch aus meiner Schulzeit, und der Lehrer dort kennt kein vector, geschweige denn irgendwas aus der STL. Dort gibt es nur "C mit Klassen". 😮 😉

    Wir mussten es so machen, auch wenn es sich unglaublich anhört.

    Gut, die Namen hätten wirklich entweder deutsch oder englisch sein können, aber zur Demo ist es denk ich mal egal.

    Und, sowas würde ich natürlich nie so machen.



  • Cybertec schrieb:

    Der Code war noch aus meiner Schulzeit, und der Lehrer dort kennt kein vector, geschweige denn irgendwas aus der STL. Dort gibt es nur "C mit Klassen". 😮 😉

    Wir mussten es so machen, auch wenn es sich unglaublich anhört.

    Gut, die Namen hätten wirklich entweder deutsch oder englisch sein können, aber zur Demo ist es denk ich mal egal.

    Und, sowas würde ich natürlich nie so machen.

    Das ist leider bittere Realität... Aber dann solltest du es jetzt besser machen als dein Lehrer.



  • Der TE wollte doch aber wissen wie es funktioniert mit new und delete, und eigentlich dachte ich dass das Beispiel es gut zeigt.

    Klar macht man das so nicht, das weis ich auch.



  • Ich tendiere auch zu einfachen Beispielen, jedoch erntet man dann immer viel Kritik 😉


  • Administrator

    Cybertec schrieb:

    Klar macht man das so nicht, das weis ich auch.

    Genau da liegt das Problem. Du weisst, dass man es so nicht macht, zeigt es aber und verkaufst es, als würde man es genau so machen. Ein Anfänger kann diesen Unterschied nicht selber erkennen.

    Grüssli



  • Dravere schrieb:

    Cybertec schrieb:

    Klar macht man das so nicht, das weis ich auch.

    Genau da liegt das Problem. Du weisst, dass man es so nicht macht, zeigt es aber und verkaufst es, als würde man es genau so machen. Ein Anfänger kann diesen Unterschied nicht selber erkennen.

    Grüssli

    Jo, klar, nur wenn der TE fragt wie man einen string mit chars macht, dann erklär ich nicht wie es funktioniert mit std::string. 😉

    Naja, egal, das Beispiel war Mist, und jetzt sollte er wissen das man es SO nicht macht. 😃


Log in to reply