How do you dynamically allocate a matrix?

前端 未结 11 852
轻奢々
轻奢々 2020-11-29 01:29

How do you dynamically allocate a 2D matrix in C++? I have tried based on what I already know:

#include 

int main(){
    int rows;
    int c         


        
相关标签:
11条回答
  • 2020-11-29 01:53

    You can also use std::vectors for achieving this:

    using std::vector< std::vector<int> >

    Example:

    std::vector< std::vector<int> > a;
    
      //m * n is the size of the matrix
    
        int m = 2, n = 4;
        //Grow rows by m
        a.resize(m);
        for(int i = 0 ; i < m ; ++i)
        {
            //Grow Columns by n
            a[i].resize(n);
        }
        //Now you have matrix m*n with default values
    
        //you can use the Matrix, now
        a[1][0]=1;
        a[1][1]=2;
        a[1][2]=3;
        a[1][3]=4;
    
    //OR
    for(i = 0 ; i < m ; ++i)
    {
        for(int j = 0 ; j < n ; ++j)
        {      //modify matrix
            int x = a[i][j];
        }
    
    }
    
    0 讨论(0)
  • 2020-11-29 01:55

    or you can just allocate a 1D array but reference elements in a 2D fashion:

    to address row 2, column 3 (top left corner is row 0, column 0):

    arr[2 * MATRIX_WIDTH + 3]

    where MATRIX_WIDTH is the number of elements in a row.

    0 讨论(0)
  • 2020-11-29 01:58

    Here is the most clear & intuitive way i know to allocate a dynamic 2d array in C++. Templated in this example covers all cases.

    template<typename T> T** matrixAllocate(int rows, int cols, T **M)
    {
        M = new T*[rows];
        for (int i = 0; i < rows; i++){
            M[i] = new T[cols];
        }
        return M;
    }
    
    ... 
    
    int main()
    {
        ...
        int** M1 = matrixAllocate<int>(rows, cols, M1);
        double** M2 = matrixAllocate(rows, cols, M2);
        ...
    }
    
    0 讨论(0)
  • 2020-11-29 02:01

    A matrix is actually an array of arrays.

    int rows = ..., cols = ...;
    int** matrix = new int*[rows];
    for (int i = 0; i < rows; ++i)
        matrix[i] = new int[cols];
    

    Of course, to delete the matrix, you should do the following:

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

    I have just figured out another possibility:

    int rows = ..., cols = ...;
    int** matrix = new int*[rows];
    if (rows)
    {
        matrix[0] = new int[rows * cols];
        for (int i = 1; i < rows; ++i)
            matrix[i] = matrix[0] + i * cols;
    }
    

    Freeing this array is easier:

    if (rows) delete [] matrix[0];
    delete [] matrix;
    

    This solution has the advantage of allocating a single big block of memory for all the elements, instead of several little chunks. The first solution I posted is a better example of the arrays of arrays concept, though.

    0 讨论(0)
  • 2020-11-29 02:03

    Using the double-pointer is by far the best compromise between execution speed/optimisation and legibility. Using a single array to store matrix' contents is actually what a double-pointer does.

    I have successfully used the following templated creator function (yes, I know I use old C-style pointer referencing, but it does make code more clear on the calling side with regards to changing parameters - something I like about pointers which is not possible with references. You will see what I mean):

    ///
    /// Matrix Allocator Utility
    /// @param pppArray Pointer to the double-pointer where the matrix should be allocated.
    /// @param iRows Number of rows.
    /// @param iColumns Number of columns.
    /// @return Successful allocation returns true, else false.
    template <typename T>
    bool NewMatrix(T*** pppArray, 
                   size_t iRows, 
                   size_t iColumns)
    {
       bool l_bResult = false;
       if (pppArray != 0) // Test if pointer holds a valid address.
       {                  // I prefer using the shorter 0 in stead of NULL.
          if (!((*pppArray) != 0)) // Test if the first element is currently unassigned.
          {                        // The "double-not" evaluates a little quicker in general.
             // Allocate and assign pointer array.
             (*pppArray) = new T* [iRows]; 
             if ((*pppArray) != 0) // Test if pointer-array allocation was successful.
             {
                // Allocate and assign common data storage array.
                (*pppArray)[0] = new T [iRows * iColumns]; 
                if ((*pppArray)[0] != 0) // Test if data array allocation was successful.
                {
                   // Using pointer arithmetic requires the least overhead. There is no 
                   // expensive repeated multiplication involved and very little additional 
                   // memory is used for temporary variables.
                   T** l_ppRow = (*pppArray);
                   T* l_pRowFirstElement = l_ppRow[0];
                   for (size_t l_iRow = 1; l_iRow < iRows; l_iRow++)
                   {
                      l_ppRow++;
                      l_pRowFirstElement += iColumns;
                      l_ppRow[0] = l_pRowFirstElement;
                   }
                   l_bResult = true;
                }
             }
          }
       }
    }
    

    To de-allocate the memory created using the abovementioned utility, one simply has to de-allocate in reverse.

    ///
    /// Matrix De-Allocator Utility
    /// @param pppArray Pointer to the double-pointer where the matrix should be de-allocated.
    /// @return Successful de-allocation returns true, else false.
    template <typename T>
    bool DeleteMatrix(T*** pppArray)
    {
       bool l_bResult = false;
       if (pppArray != 0) // Test if pointer holds a valid address.
       {
          if ((*pppArray) != 0) // Test if pointer array was assigned.
          {
             if ((*pppArray)[0] != 0) // Test if data array was assigned.
             {
                   // De-allocate common storage array.
                   delete [] (*pppArray)[0];
                }
             }
             // De-allocate pointer array.
             delete [] (*pppArray);
             (*pppArray) = 0;
             l_bResult = true;
          }
       }
    }
    

    To use these abovementioned template functions is then very easy (e.g.):

       .
       .
       .
       double l_ppMatrix = 0;
       NewMatrix(&l_ppMatrix, 3, 3); // Create a 3 x 3 Matrix and store it in l_ppMatrix.
       .
       .
       .
       DeleteMatrix(&l_ppMatrix);
    
    0 讨论(0)
提交回复
热议问题