0

In C when you declare e.g. int ar[x][y]; it actually is int[x*y], and you calls are compiled in needed manner.
But this array is stored on stack if made inside a function. I'm looking for a way to have it stored on heap, while having the same functionality. Because when I was looking for a way to do is, the only thing I found was make int** and then each of element (type int*) would be pointer to another array. (Correct me if I'm wrong) It seems legit but the second way doesn't store the values one after another and also uses more memory. For ar[x][y] first method is just x*y*sizeof(int), but for second it's x*y*sizeof(int)+x*sizeof(int*).

Summarizing is having two-dimensional array stored on heap possible, while maintaining functionality of int ar[x][y]?

EDIT: I'm sorry for misleading everyone, but ar[3][4] was just en example, I'm actually looking for a way to do this with non-constant size.

EDIT2: Actually I'm even looking for sth that will also work in raw C.

miszcz2137
  • 894
  • 6
  • 18
  • 1
    @UKMonkey In addition to Justin Randall, I would highlight this answer for C++11: [How do I declare a 2d array in C++ using new?](https://stackoverflow.com/a/16239446/7478597). I just tested something similar on my side and then found it there. – Scheff's Cat Dec 07 '17 at 16:22
  • `int (*ar)[4] = new int[3][4];`. – Jarod42 Dec 07 '17 at 16:23

1 Answers1

1

If at least one of the sizes is known at compile time, you can use standard C++ containers:

 using my2daraytype  = std::array<std::array<int, N>, M>; // both N and M are compile time constants
 // allocate this on the heap normally (e.g. with std::make_unique)
 // example
 auto myarray = std::make_unique<my2daraytype>();

Note that myarray above is a (smart) pointer to a 2d array, so you access it as (*myarray)[i][i].

 using my2daraytype = std::vector<std::array<int, N>>; // inner size N is known
 // data already lives on the heap, no need to allocate
 // example
 my2darraytype myarray(M); 

This one is not a pointer so you use myarray[i][j].

When both sizes are determined at run time, this is not so easy. std::vector<std::vector<int>> memory is organised similarly to int** so it is not suitable. You may want to create your own class that stores std::vector<int> of size M*N internally, and provide a two-argument int& operator()(size_t, size_t) for indexing. The familiar syntax with two levels of square brackets is possible but too complicated and potentially inefficient, so it's rarely worth the trouble. myarray(i,j) works perfectly so just use that.

Here's one possible basic outline of the class (unfinished, unteated) templatized for convenience:

template <class T>
class my2darray {
    std::vector<T> values;
    size_t m, n;
   public:
     my2darray(size_t m, size_t n) : values(m*n), m(m), n(n) {}
     T& operator()(size_t i, size_t j) {
          return values[i*n+j];
      }
};

It needs more code to be fully functional but this is the basis.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • I appreciate your will to help, but this is rather theoretical question with few practical uses, when I'm searching for perfect alternative for 2D array but stored on heap and your answer isn't one I'm looking for. – miszcz2137 Dec 07 '17 at 17:11
  • 1
    @miszcz2137 I'm trying my best at answering questions that were asked. If you are looking for a different answer, then maybe a different question should have been asked, or perhaps my understanding is faulty. – n. m. could be an AI Dec 07 '17 at 17:23