dynamische mehrdimensionale Arrays



  • Original erstellt von HumeSikkins:
    Hallo,
    Es gibt aber mehrere verschiedene Lösungen für dein Problem.
    1. Wenn der Speicher nich am Stück sein muss, kannst du ein Array von Zeigern auf Arrays verwenden

    int main()
    {
        const int FirstDim = 4;
        const int SecDim = 5;
        // 1. Schritt: Dynamische Array von Zeigern anlegen:
        int** p2DimArr = new int*[FirstDim];
    
        // 2. Schritt: An jeden Zeiger ein Array hängen
        for (int i = 0; i < FirstDim ; i++)
            p2DimArr[i] = new int[SecDim];
    
        // mit dem neuen 2-dimensionalen Array arbeiten
        p2DimArr[0][0] = 42;
        //...
    
        // alles wieder löschen
        for (int j = 0; j < FirstDim ; j++)
            delete [] p2DimArr[j] ;
        delete [] p2DimArr;
    }
    

    2. Wenn der Speicher am Stück sein muss, empfiehlt es sich das 2-dimensionale Array auf ein 1-dimensionales abzubilden:

    class Simple2DimArr
    {
        private:
            int* pArr;
            int Rows, Cols;
        public:
            Simple2DimArr(int Zeilen, int Spalten)
            {
                Rows = Zeilen;
                Cols = Spalten;
                // 2-Dimensionales Array auf 1-Dimensionales abbilden
                pArr = new int[Rows * Cols];
            }
            int* operator[](int Zeile)
            {
                // Array liegt "zeilenweise" im Speicher
                return & pArr[Zeile * Cols];
            }
            ~Simple2DimArr()
            {
                delete [] pArr;
            }
    };
    
    int main()
    {
        Simple2DimArr Arr(2,3);
        Arr[0][0] = 42;
    }
    

    3. Einen dritten Weg eröffnet die Verwendung von Zeigern auf Felder.
    Dieser Weg hat aber den Nachteil, dass nur wenige Leute mit deren Syntax vertraut sind:

    int main()
    {
        // Einen Zeiger auf ein Int-Array mit 5 Elementen anlegen
        int (*pArr)[5] = 0;
    
        // Den Zeiger auf ein zweidimensionales Array zeigen lassen.
        // Wichtig: Die zweite Dimension muss mit der Array-Größe
        // übereinstimmen, mit der der Zeiger deklariert wurde
        // pArr = new int [5][2]; wäre z.B. illegal, da ein Zeiger auf ein
        // Array mit 5 Elementen nicht in einen Zeiger auf ein Array mit
        // 2 Elementen konvertiert werden kann.
        pArr = new int[2][5];
        pArr[0][0] = 42;
        // ...
        // Am Ende aufräumen nicht vergessen
        delete [] pArr;
    }
    

    4. Der Weg für C++ Programmierer: Man verzichtet auf dynamische Arrays und verwendet stattdessen die Container der STL. Für den Anfang reichen vectoren. Wenn etwas schneller werden soll, bieten sich valarrays an:

    #include <vector>
    using namespace std;
    int main()
    {
        const int FirstDim = 3;
        const int SecDim = 2;
        vector< vector<int> > My2DimArr(FirstDim);
        for (int i = 0; i < FirstDim; i++)
            My2DimArr[i].resize(SecDim);
    
        My2DimArr[1][1] = 42;
    }
    

    Für den Spezialfall char-Arrays bietet sich die Klasse std::string aus der C++ Standardbibliothek an.

    Original erstellt von Dimah:
    Eine kleine Ergenzung zu Nr. 4.

    #include <vector>
    #include <cstddef> // für size_t
    using namespace std;
    
    template<typename T>
    void resize2DimVector(vector< vector<T> > & vec, size_t FirstDim, size_t SecDim)
    {
        vec.resize( FirstDim );
        for(size_t i = 0; i < FirstDim; ++i)
            vec[i].resize( SecDim );
    }
    
    template<typename T>
    const vector< vector<T> > make_2DimVector(size_t FirstDim, size_t SecDim)
    {
        vector< vector<T> > vec;
        resize2DimVector( vec, FirstDim, SecDim );
        return vec;
    } 
    
    template<typename T>
    void resize3DimVector(vector< vector< vector<T> > > & vec, size_t FirstDim, size_t SecDim, size_t ThirdDim)
    {
        vec.resize( FirstDim );
        for (size_t i = 0; i < FirstDim; ++i)
        {
            vec[i].resize( SecDim );
            for (size_t j = 0; j < SecDim; ++j)
                vec[i][j].resize( ThirdDim );
        }
    }
    
    template<typename T>
    const vector< vector< vector<T> > > make_3DimVector(size_t FirstDim, size_t SecDim, size_t ThirdDim)
    {
        vector< vector< vector<T> > > vec;
        resize3DimVector( vec, FirstDim, SecDim, ThirdDim );
        return vec;
    }
    
    int main()
    {
        vector< vector<int> > My2DimVec = make_2DimVector<int>( 100, 100 );
        My2DimVec[47][11] = 13;
        resize2DimVector( My2DimVec, 333, 333 );
        My2DimVec[222][222] = 1980;
    
        vector< vector< vector<int> > > My3DimVec = make_3DimVector<int>( 100, 100, 100 );
        My3DimVec[4][71][1] = 42;
        resize3DimVector( My3DimVec, 200, 200, 200 );
        My3DimVec[111][111][111] = 1337;
    }
    

    Die make_ Funktionen sind nur auf Compilern zu empfehlen die, die named return value Optimierung Beherrschen.


Anmelden zum Antworten