AlanKalane
AlanKalane

Reputation: 1031

A function which dynamically creates a 2d array

I want to create a dynamic 2d array in a separate function. The size of the array will be determined at runtime.

Pass an array directly:

  void foo(int **arr,int width,int height)
        {
        arr=new int*[width];
        for(int i=0;i<height;i++)
        {
        arr[i]=new int[height];
        }
        //fill...
        }
    ...
    int** array;
    foo(array)

doesn't seem to work

Pass an array via a pointer

  void foo(int ***arr,int width,int height)
        {
        *arr=new int*[width];
        for(int i=0;i<height;i++)
        {
        *arr[i]=new int[height];
        }
        //fill...
        }
    ...
    int **array;
    foo(&array)

doesnt seem to work either

How do I do that?

Upvotes: 0

Views: 65

Answers (3)

PaulMcKenzie
PaulMcKenzie

Reputation: 35440

Let's assume you have to create 2d arrays this way (with an int**).

Instead of trying to pass pointers, return the value that denotes the 2d array.

Second, your code had a bug in that you were looping over the height when you should be looping over the width. Your code would have gone into undefined behavior if height > width.

Third, I don't know if you meant width to be the first dimension or height to be the first dimension, so let's assume that what you wrote is what you meant, i.e. width is the first dimension and height is the inner dimension.

int **foo(int width, int height)
{
    int **arr = new int*[width];
    for(int i=0; i<width; i++)
       arr[i]=new int[height];
    return arr;
}
//....
int width = 10, height = 10;
int** array = foo(width, height);

Then you have to write code to delete the allocated data:

for (int i = 0; i < width; ++i)
   delete [] array [i];
delete [] array; 

Now having said the above, and the above should work, a more optimal version is found here, where the data is one contiguous block instead of separate allocated blocks. This reduces the number of times new[] and delete [] would need to be called.

Upvotes: 1

PcAF
PcAF

Reputation: 2007

I think that your "problem" is caused by ignoring operator precedence

Second code you posted seems to have mistake on line with:

*arr[i]=new int[height];

which should be

(*arr)[i]=new int[height];

Also, as other pointed out, working with raw pointers could sometimes be pretty evil (like in your example with Pointer to Pointer to Pointer), raw pointers could also cause some problems with memory leaks, dangling pointers,etc. Use something "more practical" like std::vector or some of the other STL containers.

(Note: By term "STL", I mean part of Standard library based on STL)

Upvotes: 2

Xirema
Xirema

Reputation: 20396

Generally speaking, multidimensional arrays should never, never be created like this. You should be using a single array wrapped in an object that provides row, column, table, etc. access using the operator() function.

You should also never, never be using raw pointers (except in weird, extenuating circumstances) which is why I'm using STL's std::vector class to implement your code.

class array_2d {
public:
    array_2d(size_t width, size_t height) :
    width(width),
    height(height),
    _array(width * height)
    {}

    int & operator()(size_t x, size_t y) {
        return _array[y * width + x];
    }

    const int & operator()(size_t x, size_t y) const {
        return _array[y * width + x];
    }

    std::pair<size_t, size_t> get_size() const {
        return std::make_pair<size_t, size_t>(width, height);
    }
private:
    size_t width, height;
    std::vector<int> _array;
};

int main() {
    array_2d my_array(5,5);
    my_array(3,3) = 7;
    std::cout << my_array(3,3) << std::endl;
    return 0;
}

====

7

There's a lot of stuff I didn't include (and the code would be significantly more complex if you were to implement this as a raw pointer) but this is a far superior way to write a 2-dimensional (or more dimensions, if you need it) array.

Upvotes: 1

Related Questions