简体   繁体   中英

Arbitrary Dimensional Array

So I'm trying to create an n-dimensional array structure for use in a maze generating program.

I've simplified my problem (for the purposes of trying to get the theory figured out before making it templatized and adding all the necessary helper functions)

So my problem currently boils down to wanting to make an ArbitraryArray class that takes in an argument to its constructor specifying the number of dimensions. Each dimension will have length = 5. (for now)

This is what I have so far:

class ArbitraryArray{
public:
    int array[5];
    ArbitraryArray*subArray;

    ArbitraryArray(){}

    ArbitraryArray(int depth){
        if (depth == 2) subArray = new ArbitraryArray[5];
        else if (depth > 2) for (int i = 0; i < 5; i++) subArray = new ArbitraryArray(depth - 1);
    }
};

And I'd create a 2 dimensional object like so:

ArbitraryArray testArray(2);

Or a 3 dimensional object like so:

ArbitraryArray testArray(3);

Problem is, when I tested it for depth = 3 and then tried to set an integer value, via:

testArray.subArray[3].subArray[4].array[4] = 7;

I received a runtime error, leading me to believe that I'm doing something wrong in how I allocate these objects dynamically.

Also, I included an empty default constructor since that gets called by lines like:

subArray = new ArbitraryArray[5];

I'm aware this may not be the best way to go about creating an arbitrary dimensional array data structure, but I'd really like to figure out why this implementation is not working before potentially looking for better methods.

Also I am aware I shouldn't have a line like:

int array[5];

And that it should be a pointer instead so that there isn't a ton of wasted memory allocation for all the levels of the array above the bottom dimension. And I intend to modify it to that after I get this basic idea working.

How about using std::vector for allocating the correct amount of blank memory, which would be

sizeof(T) * dim1 * dim2 * dim3 * ...

Then write a helper class which takes care of the indexing, ie, it will compute i from given (x,y,z,...) , whatever many dimensions you might have.

The beauty of this approach, IMHO, lies in not having to fiddle with pointers, and the helper class simply implements an indexing scheme of your preference ( row major or column major ).

EDIT

When using std::valarray , things may become easier, as you can use std::slice and/or std::gslice to calculate your indexing for you.

Well, for once, if depth is greater than 2, you create five ArbitraryArrays, but you save all their pointers in one SubArray pointer. SubArray needs to be an array of pointers to ArbitraryArrays, try ArbitraryArray *subArray[5]; and for (int i = 0; i < 5; i++) subArray[i] = new ArbitraryArray(depth - 1) and see what happens.

Haven't compiled anything, just visual inspection. What about this:

template<int array_length>
class ArbitraryArray{
public:
    int array[array_length];
    ArbitraryArray ** subArray;

    ArbitraryArray(){}

    ArbitraryArray(int depth){
        if (depth == 1)
            subArray = 0;
        else {
            subArray = new ArbitraryArray*[array_length];
            for (int i = 0; i < array_length; i++)
                subArray[i] = new ArbitraryArray(depth - 1);
        }
    }
};

In your example you are creating an array that is all over the place in memory instead of one array that is stored in a continuous block of memory. This could cause some issues depending on you handle the memory. eg using memcpy on it will never work.

I think a little more flexible approach would be create one large array and instead have an index into the array based on the number of dimensions

int n = static_cast<int>(pow( 5.0, static_cast<double>(depth) ));   
Type* a = new Type[ n ]; 

ie since you base your array size on 5, a 2-dim size would be 5x5 and a 3-dim 5x5x5

to access an element in the array say a[2,2,3] (0-based) it could be calculated as

a[2*5*5 + 2*5 + 3] 

Just use the Boost multi_array class. It is very flexible, efficient and can perform bounds checking.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM