How to define a 2D array in C++ and STL without memory manipulation?

纵然是瞬间 提交于 2019-12-03 03:45:27

are there other ways to define the 2D array?

No without manipulating memory explicitely (malloc/free). If you use static allocated array (1st example) you allocate the space at compile time, so you can't add more rows or columns at runtime.

The second example uses std::vector that hides to you dynamic memory allocation . This way you can eventually add more rows or columns at runtime.

If you don't need to dynamically modify the array dimension, then the first solution is the simpler and faster one (even if I think that std::vector implementation is fast enough to be comparable to static array, more elegant and more object oriented).

If you need to modify the array dimension at run-time use std::vector, because it saves you from dealing directly with malloc and free.

In C++11 use std::array:

  std::array<std::array<int,3>,2> a {{
    {{1,2,3}},
    {{4,5,6}}
 }};

Some usage:

  a[0][2] = 13;

One very efficient method to define arrays is dynamic allocation, using the new and delete operators. Here is an example:

int **arr=new int*[ROW];
for( int i=0; i<ROW; ++i ) {
  arr[i] = new int[COL];
  for( int j=0; j<COL; ++j ) {
    arr[i][j] = some_val;
  }
}

The big advantage of this approach is that when you don't need any more the memory that the array uses, you can easily delete it. Here is an example of deleting a 2D array:

for( int i=0; i<ROW; ++i ) {
  delete[] arr[i];
}
delete[] arr;   

A common pattern is encapsulating the 2D array inside a class that offers the appropriate interface. In that case, you can use other internal representations, like for example a single vector of rows*cols elements. The interface (usually operator()(int,int) will map the coordinates from the caller to a position in the linear vector.

The advantage is that it has dynamic allocation, but a single allocation (unlike the std::vector<std::vector<int>> where each vector must acquire it's own memory) and in a single block providing locality of data.

There are a lot of trade-offs here.

If you declare a C-style 2D array int array[height][width], then you really get a single contiguous block of memory. The compiler converts indexes to their 1D address

array[row][col] == *(array + row * width + col)
  • Advantages: cache coherency. All the memory is in the same place.
  • Disadvantages: you need a multiply for every indexing. Indirection might be faster.

If you use a vector of vectors, then each row is allocated separately. The outer vector stores pointers to the inner vectors. Indexing becomes an indirection followed by an addition:

array[row][col] == *(*(array + row) + col)
  • Advantages: indirection may be faster than multiplication.
  • Disadvantages: not cache coherent, since each row is allocated separately (unless the implementation optimizes for vector<vector>).

If performance is truly important, you need to test both and figure out which is faster on your data.

To declare a 2D array using std::vector, you can use this kind of construction:

vector<vector<int> >  matrix( n, vector<int>(m, -1) );

This creates a 2D array matrix of size n by m, with all elements initialised to -1.

It's basically a nesting of the "initialise with n items of value val" constructor:

vector (size_type n, const value_type& val,
                 const allocator_type& alloc = allocator_type());

(constructor definition copied from here)

kkg

If you know the elements beforehand then you could just do

int arr[2][3] = {{1,2, 3}, {4, 5, 6}};

This should be more efficient than method1 and method2. Using vectors, you are not doing memory manipulation yourself, but the vector implementation will probably use a dynamically allocated array.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!