Allocate memory for 2D array with C++ new[]

后端 未结 8 1380
情深已故
情深已故 2020-12-22 01:04

When I read some values from the user and I need to create an array of the specific size I do it somehow like this:

#include 
using namespace         


        
相关标签:
8条回答
  • 2020-12-22 01:24
    unsigned **numbers;
    numbers = new unsigned*[a];
    for (int i=0; i<a; i++){
        numbers[i] = new unsigned[b];
    }
    

    It doesn't behave exactly like a 2d array, in that it's not contiguous in memory, but it will do. You can also use the notation numbers[i][j] to access elements.

    Remember to delete[] each element of numbers at the end before delete[]-ing numbers itself

    Using std::vector is probably a preferable solution, as detailed in other posts

    0 讨论(0)
  • 2020-12-22 01:30

    If a and b are the number of rows and number of columns, respectively, you may allocate the array like this:

    new unsigned[a * b];
    

    To access the element at row i and column j, do this:

    numbers[i * b + j]
    

    However, note that in reality you're almost certainly better off using std::vector for whatever you're trying to do, but you may not have learned about that yet :)

    0 讨论(0)
  • 2020-12-22 01:32

    Updated recommendation:

    It's worth noting that boost already did that. So I'll just stick to it, if it isn't meant to be encapsulated in a class.

    Original answer:

    In general, using raw arrays and allocations is inferior to using std::vector. Now, you can of course use vector<vector<T>>, but that's not only lenghty to type, but can also involve unnecessary copying.

    Using ptr_vector or vector<unique_ptr<vector<int>> would solve the second problem, but complicate the matters even worse. So how to solve it?

    It's simple: Don't use 2D arrays at all.

    Imagine your 2D array in memory:

    [X|X|X|X]
    [Y|Y|Y|Y]
    [Z|Z|Z|Z]
    

    It's obvious enough that it could be put in one row:

    [X|X|X|X|Y|Y|Y|Y|Z|Z|Z|Z]
    

    Now we're back to old, familiar 1D array (doesn't matter if it's a vector or C-style array). In order to get to your element, you have to know the width of your initial array, and go to the array element corresponding to n'th row, then plainly add the number of columns:

    int& access (unsigned x, unsigned y) { 
        return data[x * sizeY + y]; // Or (y * sizeX + x)
    }
    

    Since it's a stub method, you might have a problem in actual usage. Here's an example of a global implementation:

    int& accessVectorAs2d (std::vector<int> & data, unsigned x, unsigned y, unsigned int sizeY); // inside stays the same
    unsigned SizeX = 20, SizeY = 20;
    std::vector<int> V (SizeX * SizeY, 0);
    
    accessVectorAs2d(V, 1, 3, SizeX) = 5;
    

    Reference is returned to allow using your 1D structure in a very similar way to normal 2D array:

    // So you can do either reads
    int X = access(1, 3);
    
    // Or writes!
    access(1,3) = 5;
    

    Additional note: if you'll construct your own class, overloading operator() can give you even better results:

    Data(1, 3) = 5;
    int X = Data(1, 3);
    

    Now how you're gonna implement that access (subclassing or encapsulating vector, or just using plain global function) doesn't really matter.

    I'd strongly suggest you used std::vector here. It will ensure no memory will leak (forgotten delete), it will be easier to change the size (either by .push_back() or .reserve()) and is in general suggested practice; you're writing in C++, not in C, after all.

    Behold! Dragons after this point!

    Actually the class should of course be templated, with not only the type, but also number of dimensions (okay, that can be simplified) and size of (every-1) dimension (-1 to allow unlimited growth in one side). This would be probably done best by creating appropriate access functions at compile time, calculating

    Sumi = 0i < n (Sizei)i * Di,

    where n is number of dimensions, S is an array of dimension sizes, and D is an array of coordinates.

    0 讨论(0)
  • 2020-12-22 01:32

    Try to use vectors.

    #include <iostream>
    #include <vector>
    using namespace std;
    
    int main()
    {
    // An empty vector of vectors. The space 
    // between the 2 '>' signs is necessary
    vector<vector<int> > v2d;
    
    // If you intend creating many vectors 
    // of vectors, the following's tidier
      typedef vector<vector<int> > IntMatrix;
      IntMatrix m;
    
    // Now we'll try to create a 3 by 5 "matrix".
    // First, create a vector with 5 elements
       vector<int> v2(5, 99); 
    
    // Now create a vector of 3 elements. 
     // Each element is a copy of v2
     vector<vector<int> > v2d2(3,v2);
    
    // Print out the elements
     for(int i=0;i<v2d2.size(); i++) {
      for (int j=0;j<v2d2[i].size(); j++)
        cout << v2d2[i][j] << " "; 
        cout << endl;
       }
    }
    
    0 讨论(0)
  • 2020-12-22 01:35

    Could just use one vector to represent two dimension arrays:

       typedef std::vector<int>     d1_type;       // 1D
       typedef std::vector<d1_type> d2_type;       // 2D
       typedef std::vector<d2_type> d3_type;       // 3D
    
    
       int num = 5;
       d2_type value2d(num, d1_type(num));
       d3_type value3d(num, d2_type(num, d1_type(num)));
    

    And you can access 2D/3D vector like array, for example:

     value2d[0][0] = 100;
     value3d[0][0][0] = 100;
    
    0 讨论(0)
  • 2020-12-22 01:35

    You can allocate the memory by using c++ new[] the following way :

    int** array = new int*[x];
    for(int i = 0; i < x; i++)
        aryay[i] = new int[y];
    

    The simple concept of this is that its and array of pointers which are pointing to arrays. It must be deleted too to avoid the memory leaks.

    0 讨论(0)
提交回复
热议问题