Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing array with unknown size to function

Tags:

c++

arrays

Let's say I have a function called MyFunction(int myArray[][]) that does some array manipulations.

If I write the parameter list like that, the compiler will complain that it needs to know the size of the array at compile time. Is there a way to rewrite the parameter list so that I can pass an array with any size to the function?

My array's size is defined by two static const ints in a class, but the compiler won't accept something like MyFunction(int myArray[Board::ROWS][Board::COLS]).

What if I could convert the array to a vector and then pass the vector to MyFunction? Is there a one-line conversion that I can use or do I have to do the conversion manually?

like image 348
Pieter Avatar asked Oct 21 '10 19:10

Pieter


2 Answers

In C++ language, multidimensional array declarations must always include all sizes except possibly the first one. So, what you are trying to do is not possible. You cannot declare a parameter of built-in multidimensional array type without explicitly specifying the sizes.

If you need to pass a run-time sized multidimensional array to a function, you can forget about using built-in multidimensional array type. One possible workaround here is to use a "simulated" multidimensional array (1D array of pointers to other 1D arrays; or a plain 1D array that simulates multidimensional array through index recalculation).

like image 176
AnT Avatar answered Oct 28 '22 22:10

AnT


In C++ use std::vector to model arrays unless you have a specific reason for using an array.

Example of a 3x2 vector filled with 0's called "myArray" being initialized:

vector< vector<int> > myArray(3, vector<int>(2,0));

Passing this construct around is trivial, and you don't need to screw around with passing length (because it keeps track):

void myFunction(vector< vector<int> > &myArray) {
    for(size_t x = 0;x < myArray.length();++x){
        for(size_t y = 0;y < myArray[x].length();++y){
            cout << myArray[x][y] << " ";
        }
        cout << endl;
    }
}

Alternatively you can iterate over it with iterators:

void myFunction(vector< vector<int> > &myArray) {
    for(vector< vector<int> >::iterator x = myArray.begin();x != myArray.end();++x){
        for(vector<int>::iterator y = x->begin();y != x->end();++y){
            cout << *y << " ";
        }
        cout << endl;
    }
}

In C++0x you can use the auto keyword to clean up the vector iterator solution:

void myFunction(vector< vector<int> > &myArray) {
    for(auto x = myArray.begin();x != myArray.end();++x){
        for(auto y = x->begin();y != x->end();++y){
            cout << *y << " ";
        }
        cout << endl;
    }
}

And in c++0x for_each becomes viable with lambdas

void myFunction(vector< vector<int> > &myArray) {
    for_each(myArray.begin(), myArray.end(), [](const vector<int> &x){
        for_each(x->begin(), x->end(), [](int value){
            cout << value << " ";
        });
        cout << endl;
    });
}

Or a range based for loop in c++0x:

void myFunction(vector< vector<int> > &myArray) {
    for(auto x : myArray){
        for(auto y : *x){
            cout << *y << " ";
        }
        cout << endl;
    }
}

*I am not near a compiler right now and have not tested these, please feel free to correct my examples.


If you know the size of the array at compile time you can do the following (assuming the size is [x][10]):

MyFunction(int myArray[][10])

If you need to pass in a variable length array (dynamically allocated or possibly just a function which needs to take different sizes of arrays) then you need to deal with pointers.

And as the comments to this answer state:

boost::multiarray may be appropriate since it more efficiently models a multidimensional array. A vector of vectors can have performance implications in critical path code, but in typical cases you will probably not notice an issue.

like image 39
M2tM Avatar answered Oct 28 '22 23:10

M2tM