开发者

C++ 2D Dynamic Array

I am trying to dynamically assign a 2d array to a pointer in a constructor initialize.

FooBar::FooBar()
    : _array( new int[10][10] )
{ }
int **_array;

However this does not wor开发者_开发技巧k. I understand that multidimensional arrays are allocated a bit differently. Is anyone able to elaborate on this with an explanation?

Thanks in advance.


Some answers here say a 2-dimensional array is an array of pointers to other arrays. That's not true (where to store pointers, if all you allocate is the data of the array!?). Instead, a 2-dimensional array is an array of other arrays. Thus, you will have to change the type of your member:

FooBar::FooBar()
    : _array( new int[10][10] )
{ }
int (*_array)[10];

That is because new[] returns a pointer to the first element of an array created. This element is an array of 10 integers, and thus the member type change. If the syntax scares you off, simplify it with a temlate (this template is equivalent to boost::identity).

template<typename T> struct identity { typedef T type; };

FooBar::FooBar()
    : _array( new int[10][10] )
{ }
identity<int[10]>::type *_array;

This effectively works like a in-place typedef. Of course, like with any use of new[], it needs a proper delete[] placed in the destructor and invoked when your object is destroyed.

Since new[] allocates an array of elements that have types known at compile time, you can only have the first (most outer) dimension set to a runtime value - all others must have values known at compile time. If that is not what you want, you will have to allocate an array of pointers, like some other answers say.

But notice, to avoid further confusion, that those are not multi-dimensional arrays. They are single-dimensional arrays of pointers, which happen to point at other single-dimensional arrays.


A 2-dimensional array in C is an array of pointers to other arrays.

Assuming we have the 3x3 array a (typed int**):

a[0] (a[0] is of type int*) = [0][1][2]
a[1] (a[1] is of type int*) = [0][1][2]
a[2] (a[2] is of type int*) = [0][1][2]

That means that two allocation passes are needed, one for the array of pointers, (int**) and the rest is for each of that array's elements.

First pass, allocating an array of pointers:

int** a = new int*[10];

Second pass, for each of a's elements, allocating a new array:

for(int i=0; i<10; ++i)
    a[i] = new int[10];

This will give you a 'two' dimensional array in C++.

As you can see, this can be pretty cumbersome in higher dimensions, so another trick is to allocate 10*10 elements and use the array as 2D (aka "projection"):

const int ARRAY_WIDTH = 10;
const int ARRAY_HEIGHT = 10;
int* a = new int[ARRAY_WIDTH * ARRAY_HEIGHT];

    // To access a[5][2] you would use: 
a[5 + (2 * ARRAY_WIDTH)] = 0;


int **array  = new int *[10];

for(int i= 0; i< 10;i++)
{
    array[i] = new int[10];
}


If you're using new, you need to allocate each piece of the second dimension individually.

int **Array;
Array = new int*[10];
for (int i = 0; i < 10; i++) {
    Array[i] = new int[10];
}


If you don't care much about performance you can use the following:

//vec2d.h
#include<vector>

template<class T>
void init2DVect(std::vector< std::vector<T> >& _T, size_t sx, size_t sy)
{
  _T.resize( sx );
  for(size_t i =0; i < sx; ++i)
  {
    std::vector<T> ins_v(sy);
    _T[i] = ins_v;
  }
}

Example use-case:

//file: vec2d_test.cpp
#include "vec2D.h"

#include<cassert>

int main()
{
  std::vector< std::vector<int> > vi;
  size_t sx = 5;
  size_t sy = 7;
  init2DVect(vi, sx, sy);

  for(size_t i = 0; i < sx; ++i)
  {
    for(size_t j = 0; j < sy; ++j)
    {
      vi.at(i).at(j) = i*j;
    }
  }

  for(size_t i = 0; i < sx; ++i)
  {
    for(size_t j = 0; j < sy; ++j)
    {
      assert( vi.at(i).at(j) == i*j );
      assert( vi[i][j] == i*j );
    }
  }   

  return 0;
}

This has the advantage that you don't have to worry about memory and you can use the vector::at() function in order to throw an exception if you are out of bounds... good for C++ homework, but a vector of std::vector is bound to not be the fastest way to do it.

Othewise the TNT library does the trick.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜