Passing pointer of multi-dimensional pointer array to a function - c++

ok so suppose I have a function myFunction. Then in main i have a multi dimensional array of pointers. I want to pass a pointer to this array of pointers into myFunction. How would I do that? I know that If you want to pass an int to my function, one can write the function as
myfunct( int x) { ...}
What would that type of x be if I have to pass a pointer to an array of pointers? Thanks in advance :D

Typically you want to modify the elements of an array rather then the actual pointer. The actual pointer is given by malloc and if you change it, by writing directly to the value, it won't affect the memory allocation (except you might loose the initial pointer...).
This might be what you're looking for in a 2D array.
void myfunct(int** ptr,int items, int array_items)
{
//some code
}
int main(int argc, char *argv[])
{
const auto items = 5;
const auto array_items = 7;
int** multi_dimensional_array = reinterpret_cast<int**>(std::malloc(items * sizeof(int*)));
for (auto i = 0 ;i < items;++i)
{
multi_dimensional_array[i] = static_cast<int*>(std::malloc(sizeof(int) * array_items));
}
myfunct(multi_dimensional_array,items,array_items);
//deallocate
}

Wrap your multidimensional array inside a class. That way you can carry the data and dimensions in one block and passing it around is as simple as moving around any other class.
Remember to observe the Rules of Three, Five, and Zero, whichever best applies to how you store your array inside your class. std::vector is a personal favourite because it allows you to use the Rule of Zero.
For example:
#include <iostream>
#include <vector>
struct unspecified
{
};
template<class TYPE>
class TwoDee{
int rows;
int cols;
std::vector<TYPE> data;
public:
TwoDee(int row, int col):rows(row), cols(col), data(rows*cols)
{
// does nothing. All of the heavy lifting was in the initializer
}
// std::vector eliminates the need for destructor, assignment operators, and copy
//and move constructors. All hail the Rule of Zero!
//add a convenience method for easy access to the vector
TYPE & operator()(size_t row, size_t col)
{
return data[row*cols+col];
}
TYPE operator()(size_t row, size_t col) const
{
return data[row*cols+col];
}
};
void function(TwoDee<unspecified *> & matrix)
{
// does stuff to matrix
}
int main()
{
TwoDee<unspecified *> test(10,10);
function(test);
}

To directly answer your question, typically the type passed will be int * for a vector of int, and int ** for a 2D array of int
void myfunct( int **x)
{
x[2][1] = 25;
return;
}
If for some reason you wanted that to be an array of int pointers instead of int you need an extra *.
void myfunct( int ***x)
{
*(x[2][1]) = 25;
return;
}

Let me first try to interpret the exact type that you want to deal with. I suppose in your main function there is a "multidimensional array" which stores pointers for each element. As an example, let's say you have a 3-dimensional array of pointer to integer type.
Assume that you know the size of the array:
C style array will look like this:
int *a[4][3][2];
that means a is a 4x3x2 array, and each element in the array is a pointer to integer. So overall you now have 24 pointers to integer in total, as can be seen by testing the result of sizeof(a) / sizeof(int*) (the result should be 24). Okay, so far so good. But now I guess what you want is a pointer to the array a mentioned above, say b, so b is defined
int *(*b)[4][3][2] = &a;
Notice that although now b looks intimidating, in the end it is just a pointer which just stores an address, and sizeof(b) / sizeof(int*) gives 1 as the result. (The * inside parenthesis indicates b is pointer type, so b is a pointer to a "multidimensional array" of pointers to integer.)
Now to pass b to myFunction, just give the same type of b as argument type in the declaration:
void myFunction(int *(*x)[4][3][2]) {
// do something
}
And that's it! You can directly use myFunction(b) to invoke this function. Also, you can test that inside myFunction, x is still of the size of one pointer, and *x is of the size of 24 pointers.
*Note that since we are passing a pointer to array type into the function, the array-to-pointer decay does not apply here.
Assume you don't know the size of the array at compile time:
Say you have int N1 = 4, N2 = 3, N3 = 2; and you want to initialize a N1xN2xN3 array of pointer to integer, you cannot directly do that on the stack.
You could initialize use new or malloc as suggested in #Mikhail's answer, but that approach takes nested loops for multidimensional arrays and you need to do nested loops again when freeing the memory. So as #user4581301 suggests, std::vector provides a good wrapper for dynamic size array, which do not need us to free the memory by ourselves. Yeah!
The desired array a can be written this way (still looks kind of ugly, but without explicit loops and bother of freeing memory)
std::vector<std::vector<std::vector<int*>>> a (N1,
std::vector<std::vector<int*>> (N2,
std::vector<int*> (N3)
)
);
Now, b (the pointer to a) can be written as
auto *b = &a;
You can now pass b with
void myFunction(std::vector<std::vector<std::vector<int*>>>* x) {
// do something
}
Notice that the * before x means x is a pointer.

Related

C++ Pointer not being updated?

Not exactly sure how to word the title but I'll explain as best I can.
I have a program that originally used a 2D array of a set size and so it was defined as:
typedef char Map[Row][Col];
I'm now trying to dynamically allocate memory for it and it has now also become of variable size based on input. It's now defined as:
typedef char** Map;
In my main method, I originally had:
Map map;
readUserInput(map);
Basically readUserInput takes the map array as a parameter, and assigns values to it based on user input. The map then contains values and is used in other functions.
I've updated the readUserInput function so that it dynamically sizes the array and it allocates/deallocates memory for it. This works fine, but the problem comes from the fact that now in the main method, map is not being updated. The above code in main now looks like:
Map map = nullptr;
readUserInput(map);
but after running the readUserInput function, map is still null. Inside of the function, map is updated fine, so I'm not understanding the difference made between the changes.
What you pass to function is a pointer to array and fuction can't change it. But replacing array with pointer to pointer is incorrect in most case.Pointer to pointer suggest that have a 1D array of pointers. Which may (or may not) point to other arrays. Such data organization sometimes referred to as jagged arrays, because it allows each row to be of separate length. But on practtice jagged arrays and their subclass, sparse matrices, usually implemented as 1D array to avoid re-allocation.
To avoid decaying and to actually store a monolithic array in memory, you should use 1d array and, preferably, encapsulation for pointer arithmetic and reallocation, and then pass reference to object that stores all required states. Reference ensures that object is mutable by function ( a smart-pointer-less version for an example):
class Map
{
int rows, cols;
char *data;
public:
Map() : rows(), cols(), data(nullptr) {}
Map(int r, int c) : rows(r), cols(c), data(new char[r*c]()) {}
~Map() { delete[] data; }
void resize(int r, int c) {
if(rows == r && cols == c) return;
char* tmp = new char[r*c]();
if(data)
{
// copy old data here if required
delete[] data;
}
row = r; col = c;
data = tmp;
}
char& operator() (int r, int c) { return data[r*cols + c]; }
char operator() (int r, int c) const { return data[r*cols + c]; }
};
NB: this class requires a copy and move operations to be implemented if any copy must be allowed.
The function prototype would be:
void readUserInput(Map& map);
With such class you can do dynamic resizing, store its size, and address element as simple as this:
int main()
{
Map test(4, 5); // declaring and allocating memory
test.resize(3,3); // reallocating
test(1,1) = 3; // writing
//reading
std::cout << +test(1,1) << std::endl;
}
The function should accept the array by reference in the C terms like
readUserInput( &map );
when the function is declared like
void readUserInput( Map *map );
or in the C++ terms when the function is declared like for example
void readUserInput( Map &map );
and called like
readUserInput(map);
Instead of allocating dynamically arrays you could use the container std::vector<std::string>.
The code you have used is a pure C-style code, and is prone to many mistakes:
You use typedef instead of: using Map = char**;
You use a function which gets a pointer and fills it, which is more common in C than in C++.
You use raw pointer instead of smart pointers (added in C++11), which may cause a memory leak in the end.
I've updated the readUserInput function so that it dynamically sizes the array and it allocates/deallocates memory for it.
This means that now it should be a class named Map, since it should be able to allocate/deallocate, insert and remove values, and is a valid container. Actually, you are creating a type of std::vector here, and if you don't create it for you own learning process, I strongly suggest you to use the std containers!
It is possible to pass both pointer and references in C++, notice that:
You can pass a reference only if the value isn't nullptr.
When there should be a value, reference is recommended.
In this case, your function should look like
void readUserInput(Map* map);
and should be called using:
readUserInput(&map);

Cannot convert double [] [] to double **

I ve got a function that takes 3 parameteres, first one is **double.
normalizeDataZeroMeanUnitSD(double ** trainingActions, int numberOfTrainingActions, int descriptorDimension)
When I call it from main, I am trying to use normalizeDataZeroMeanUnitSD(data, 681, 24); however, I am receiving
cannot convert parameter 1 from 'double [681][24]' to 'double **'
This is how I construct the data array:
fstream infile;
infile.open("gabor\\Data.txt");
double data[681][24];
while (!infile.eof())
{
for(int j=0;j<681;j++)
{
for(int k=0; k<24;k++)
{
infile >> data[j][k];
}
}
}
infile.close();
Is there a way to do the same using **data?
The error is pretty clear: Datatype double [681][24] is not the same as double **. While it's true that double[681] can decay to a pointer to its first element (thus, double*), that does not imply that double[681][24] can decay to double**.
Think about it this way: double** implies a pointer to many pointers. But double[][] does not have ANY pointers in it. At best, an array of ANY dimensions still only has, at very most, one pointer: to the beginning of its contiguous storage.
You could use a template:
template<std::size_t M, std::size_t N>
void normalizeDataZeroMeanUnitSD(double (&trainingActions)[M][N], int descriptorDimension)
{
for( std::size_t m = 0; m < M; ++m )
{
for( std::size_t n = 0; n < N; ++n )
{
trainingActions[m][n] = ...;
}
}
}
But beware of code bloat if you call this with many differently sized arrays.
Use any of the following declarations. Both are equivalent.
NormalizeDataZeroMeanUnitSD(double trainingActions[][24], int numberOfTrainingActions, int descriptorDimension)
NormalizeDataZeroMeanUnitSD(double trainingActions[681][24], int numberOfTrainingActions, int descriptorDimension)
When you declare a 2D array it takes up contiguous memory locations. So you need to specify at least the number of columns (in case of row major architecture).
For row major and column major definitions, have a look at this.
For your edited question, yes you can declare using **data. Dynamically allocate the data array. But remember to free it when you're done with it.
double **data=new double*[681];
for (int i=0;i<681;i++)
{
data[i]=new double[24];
}
//do what you want to do
for (int i=0;i<681;i++)
{
delete [] data[i];
}
delete [] data;
Now your function prototype can be like void func(double **pp) because data is a pointer not a 2D array.
A 2d array is a continuous area of storage. The function expects a pointer to pointers. These are incompatible.
The function expects an array of pointers to arrays; you have an array of arrays. Some options are:
change the function to take a more friendly type, perhaps double* pointing to the first element of a contiguous 2-dimensional array; or
build a separate array of pointers pointing to each row of your 2-dimensional array; or
restructure your data into an array of pointers to arrays.
Here is a constructive answer for how to make it work.
Basically, you need to generate an array that has pointers to each 1D slice of your 2D array.
double data[N][M] = {...};
double *dataPtrs[N];
for(size_t n=0; n<N; ++n) {
dataPtrs[n] = data[n];
}
normalizeDataZeroMeanUnitSD(dataPtrs, N, M); // order of N and M might be wrong
Yay, I get to rant about this again.
In C++, despite having similar syntax, 2D arrays are NOT jagged arrays. 2D arrays (double foo[681][24]) are allocated contiguously in memory. When you deference a 2D array (foo[j][i]) it actually does *(foo+24*i+j). This is all done under the hood. The sizeof(foo)==sizeof(double)*681*24.
Jagged arrays are (double** bar;). This is a bunch of different arrays: first, you allocate an array of pointer, 268 members long. Each pointer will point to an array of doubles, 24 elements long. Bar is just a pointer, so sizeof(bar)==sizeof(void*).
More annoyingly, 2D arrays (or a static array of any dimension) behave the opposite of all other types in C++ in the following reguard: they are passed implicitly by reference, causing the weird phenomenon below.
void foo(double bar[24][24]) { std::cout << sizeof(bar) << std::endl;}
int main() {
double test[24][24];
std::cout << sizeof(test) << std::endl;//returns sizeof(double)*24*24
foo(test);//returns sizeof(void*), implicitly passed by reference, opossite of the rest of c++!
double[][] is not the same thing as double**.
double** is a pointer to pointers.
double[][] is a 2-dimensional array allocated as continuous storage.
In order to pass a "2-dimensional array" to the function, you need to create an array of pointers to arrays. For example:
double* array_2d[681];
for(unsigned int i=0; i<681; ++i) {
array_2d[i] = new double[24];
}
normalizeDataZeroMeanUnitSD(array_2d, 681, 24);
Remember to later delete[] each element of array_2d!
Better yet, change normalizeDataZeroMeanUnitSD to take a reference to std::vector<std::vector<double>>, and you no longer have to worry about memory management, nor passing the correct dimensions to the function.

Passing by reference 3-Dim Fixed length array

Can anyone hint on how to pass by reference an array of the kind
int array[2][3][4];
so that I may save his pointer in order to use and modify the array?
Like, if I were speaking about a single integer:
// Scope 1
int a = 3;
increment(&a);
// End Scope 1
// Scope 2
int *pa;
void increment(int *tpa) {
pa = tpa; *pa++;
}
// End Scope 2
Thanks a lot and best regards.
If you really want to pass the array by reference, you can do so:
void f(int (&a)[2][3][4]) { }
In C, which doesn't have references, you can pass the array by pointer (this works in C++ too, of course):
void f(int (*a)[2][3][4]) { }
C++:
void f(int (&array)[2][3][4])
{
}
C: There are no references in C
Note that no matter how you pass the array, via reference or not, the array is not going to be copied, so you'll get the original pointer. You can pass this array also like this:
void f(int array[][3][4])
{
}
Thanks to everyone who participated in this! sskuce provided a very good solution, taking advantage of a "container". I had thought about this but didn't really like the extra stuff.
I realized after a little jumbling that James McNellis had given the answer all along. So... here's the solution I prefer with no containers and no indexes arithmetic (mind the parenthesis):
void Scope1()
{
int array[2][3][4];
Scope2(&array);
}
int (*pArray)[2][3][4];
void Scope2(int (*tpArray)[2][3][4]))
{
pArray = tpArray;
(*pArray)[0][0][0] = 3;
}
Thanks again to everyone.
Edit: I'm keeping my original answer below, as I believe it's necessary for folks to understand how arrays are actually passed to functions and how they're layed out in memory, but on further reflection I think there is a simple and correct way to get what you want done.
Encapsulate the array within a struct, e.g.
typedef struct ArrayHolderStruct{
int array[2][3][4];
} ArrayHolder
//...
//scope 1
ArrayHolder thingy;
thingy.array[0] = something;
//other initialization.
F( &thingy );
//...
//scope 2
ArrayHolder *pa;
void F ( ArrayHolder *p ){
pa = p;
p->array[0][1][2] = 42;
}
//Call F first to set pa.
void G(){
pa->array[0][1][2] = 6 * 9; // if pa = &thingy, thingy will be modified.
}
The struct will allow you to maintain layout information about the encapsulated array, and you don't have to worry about nasty index arithmetic.
-----OLD ANSWER-----
Passing a reference to an array is not useful, unless you want to change the size or layout of the array (which you can't do with statically sized arrays anyway). You'll get a reference (or pointer) to the elements of the array even if you pass the array by "value". That is to say, if you declare your function:
void f ( int a[2][3][4] ){
a[0][1][2] = 42;
}
and call it like f( array ) when f exits, array[0][2][2] will have been set to 42, even though you didn't pass a "reference" to array into the function.
If you want to save a pointer to the array for later use in a library function, etc, you could do something like:
//scope 2
int * pa;
void f ( int a[2][3][4] ){
pa = &a[0][0][0];
}
It gets tricky at this point - you have to know how pa is layed (laid?) out in memory. I think C has standardized on 'row major order', so the array should be layed out in memory like:
a[0][0][0] a[0][0][1] a[0][0][2] a[0][0][3] a[0][1][0] ... a[0][2][3] a[1][0][0] a[1][0][1]... a[1][2][3]
So, to get at an element at index [n][j][k], you have to do something like:
pa[n * 12 + j * 4 + k] = something;
Basically, multiply each index by the number of elements that can be referenced by an index of that order, e.g. each k index points to exactly one element given a fixed j and n index, each j index can point to 4 elements given a fixed n index, and each n index can point to one of 12 (because 12 = 3 * 4) elements.
Like I said, it's tricky. See the wikipedia articles on Array Data Structures and Row-major order to get a better understanding of how these things are layed out.

Passing array with unknown size to function

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?
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).
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.
Pass it as a pointer, and take the dimension(s) as an argument.
void foo(int *array, int width, int height) {
// initialize xPos and yPos
assert(xPos >= 0 && xPos < width);
assert(yPos >= 0 && yPos < height);
int value = array[yPos * width + xPos];
}
This is assuming you have a simple two-dimensional array, like int x[50][50].
There are already a set of answers with the most of the common suggestions: using std::vector, implementing a matrix class, providing the size of the array in the function argument... I am only going to add yet another solution based on native arrays --note that if possible you should use a higher level abstraction.
At any rate:
template <std::size_t rows, std::size_t cols>
void function( int (&array)[rows][cols] )
{
// ...
}
This solution uses a reference to the array (note the & and the set of parenthesis around array) instead of using the pass-by-value syntax. This forces the compiler not to decay the array into a pointer. Then the two sizes (which could have been provided as compile time constants can be defined as template arguments and the compiler will deduct the sizes for you.
NOTE: You mention in the question that the sizes are actually static constants you should be able to use them in the function signature if you provide the value in the class declaration:
struct test {
static const int rows = 25;
static const int cols = 80;
};
void function( int *array[80], int rows ) {
// ...
}
Notice that in the signature I prefer to change the double dimension array for a pointer to an array. The reason is that this is what the compiler interprets either way, and this way it is clear that there is no guarantee that the caller of the function will pass an array of exactly 25 lines (the compiler will not enforce it), and it is thus apparent the need for the second integer argument where the caller passes the number of rows.
You can't pass an arbitrary size like that; the compiler doesn't know how to generate the pointer arithmetic. You could do something like:
MyFunction(int myArray[][N])
or you could do:
MyFunction(int *p, int M, int N)
but you'll have to take the address of the first element when you call it (i.e. MyFunction(&arr[0][0], M, N).
You can get round all of these problems in C++ by using a container class; std::vector would be a good place to start.
The compiler is complaining because it needs to know the size of the all but the first dimension to be able to address an element in the array. For instance, in the following code:
int array[M][N];
// ...
array[i][j] = 0;
To address the element, the compiler generates something like the following:
*(array+(i*N+j)) = 0;
Therefore, you need to re-write your signature like this:
MyFunction(int array[][N])
in which case you will be stuck with a fixed dimension, or go with a more general solution such as a (custom) dynamic 2D array class or a vector<vector<int> >.
Use a vector<vector<int> > (this would be cheating if underlying storage was not guaranteed to be contiguous).
Use a pointer to element-of-array (int*) and a size (M*N) parameter. Here be dragons.
First, lets see why compiler is complaining.
If an array is defined as int arr[ ROWS ][ COLS ]; then any array notation arr[ i ][ j ] can be translated to pointer notation as
*( arr + i * COLS + j )
Observe that the expression requires only COLS, it does not require ROWS. So, the array definition can be written equivalently as
int arr [][ COLS ];
But, missing the second dimension is not acceptable. For little more details, read here.
Now, on your question:
Is there a way to rewrite the
parameter list so that I can pass an
array with any size to the function?
Yes, perhaps you can use a pointer, e.g. MyFunction( int * arr );. But, think about it, how would MyFunction() know where to stop accessing the array? To solve that you would need another parameter for the length of the array, e.g. MyFunction( int * arr, size_t arrSize );
Yes: MyFunction(int **myArray);
Careful, though. You'd better know what you're doing. This will only accept an array of int pointers.
Since you're trying to pass an array of arrays, you'll need a constant expression as one of the dimentions:
MyFunction(int myArray[][COLS]);
You'll need to have COLS at compile time.
I suggest using a vector instead.
Pass a pointer and do the indexing yourself or use a Matrix class instead.
yes - just pass it as pointer(s):
MyFunction(int** someArray)
The downside is that you'll probably need to pas the array's lengths as well
Use MyFunction(int *myArray[])
If you use MyFunction(int **myArray) an pass int someArray[X][Y], the program will crash.
EDIT: Don't use the first line, it's explained in comments.
I don't know about C++, but the C99 standard introduced variable length arrays.
So this would work in a compiler that supports C99:
void func(int rows, int cols, double[rows][cols] matrix) {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
printf("%f", matrix[r][c]);
}
}
}
Note that the size arguments come before the array. Really, only the number of columns has to be known at compile time, so this would be valid as well:
void func(int rows, int cols, double[][cols] matrix)
For three or more dimensions, all but the first dimension must have known sizes. The answer ArunSaha linked to explains why.
Honestly, I don't know whether C++ supports variable-length arrays, so this may or may not work. In either case, you may also consider encapsulating your array in some sort of matrix class.
EDIT: From your edit, it looks like C++ may not support this feature. A matrix class is probably the way to go. (Or std::vector if you don't mind that the memory may not be allocated contiguously.)
Don't pass an array, which is an implementation detail. Pass the Board
MyFunction(Board theBoard)
{
...
}
in reality 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]).
That's strange, it works perfectly fine for me:
struct Board
{
static const int ROWS = 6;
static const int COLS = 7;
};
void MyFunction(int myArray[Board::ROWS][Board::COLS])
{
}
Maybe ROWS and COLS are private? Can you show us some code?
In C++, using the inbuilt array types is instant fail. You could use a boost::/std:: array of arrays or vector of arrays. Primitive arrays are not up to any sort of real use
In C++0x, you can use std::initializer_list<...> to accomplish this:
MyFunction(std::initializer_list<std::initializer_list<int>> myArray);
and use it (I presume) like this (with the range based for syntax):
for (const std::initializer_list<int> &subArray: myArray)
{
for (int value: subArray)
{
// fun with value!
}
}

Pointer Pointer Methods C++

I have two questions:
1) How can I make an array which points to objects of integers?
int* myName[5]; // is this correct?
2) If I want to return a pointer to an array, which points to objects (like (1)) how can I do this in a method? ie) I want to impliment the method:
int **getStuff() {
// what goes here?
return *(myName); // im pretty sure this is not correct
}
Thanks for the help!
How can I make an array which points
to objects?
int * myName[5]; /* correct */
If I want to return a pointer to an
array, which points to objects (like
(1)) how can I do this in a method?
Technically, you write this function:
int * (* getStuff() )[5] {
return &myName;
}
That returns a pointer to that array. However, you don't want to do that. You wanted to return a pointer to the first element of the array:
int ** getStuff() {
return myName; /* or return &myName[0]; */
}
That way, you can now access items as you want like getStuff()[0] = &someInteger;
Note that your code,
int* myName[5];
declares an array containing 5 values, each of which is a "pointer to int", which is what you asked.
However this being C++, that's all it does. As a Python scripter, that might cause you some surprises.
It does not give any of those 5 pointers sensible values, and it does not create any integers for them to point to.
If you put it in a function body, then it creates the array on the stack. This means that the array will cease to exist when the current scope ends (which, to put it simply, means when you get to the enclosing close-curly, so for example return does it). So in particular, the following code is bad:
int **myFunction() {
int *myArray[5];
return myArray;
} // <-- end of scope, and return takes us out of it
It might compile, but the function returns a pointer to something that no longer exists by the time the caller sees it. This leads to what we call "undefined behaviour".
If you want the array to exist outside the function it's created in, you could create one on the heap each time your function is called, and return a pointer, like this:
int **myFunction() {
int **myArray = new int[5];
return myArray;
}
The function returns a different array each time it's called. When the caller has finished with it, it should destroy the array, like this:
delete[] myArray;
otherwise it will never be freed, and will sit around using up memory forever (or when your program exits on most OSes).
Alternatively, you can use the keyword "static" to create an array with "global storage duration" (meaning that it exists as long as the program is running, but there's only one of it rather than a new one each time). That means the function returns the same array each time it's called. The caller could store some pointers in it, forget about it, call the function again, and see the same pointers still there:
int **myFunction() {
static int *myArray[5];
return myArray;
}
Note how similar this code is to the very bad code from earlier.
Finally, if you just want to create an array of integers, not an array of pointers to integers, you can do this:
int myArray[5] = { 1, 2, 3, 4, 5};
That actually creates 5 integers (meaning, it assigns space which can store the integer values themselves. That's different from the array of pointers, which stores the addresses of space used to store integer values).
It also stores the specified values in that space: myArray[0] is now 1, myArray[1] is 2, etc.
1) Correct - this is an array of 5 pointers to ints
2) You can return a pointer to an array of pointers to ints by returning a pointer to the first element of that array. This has two levels of indirection, so you need two asterisks. You can also return the array normally, since arrays automatically decay into pointers to their first elements.
int **getStuff() {
return myName; // 1
return &myName[0]; // 2
}
int **myName;
int **getStuff() {
int **array = new int*[5];
for (int i = 0; i < 5; i++)
{
int key = i;
array[i] = &key;
}
return array;
}
Steve Jessop, I think you meant:
int **myFunction() {
int **myArray = new int*[5];
return myArray;
}
This returns a heap array pointer (not pointer to its elements), testable and deletable. Nothing leaks.
template <class T>
T* newarray(int len)
{
T *a;
try
{
a = new T[len];
memset(a,0,len*sizeof(T));
return a;
}
catch (...)
{return 0;}
}
.
.
.
void foo()
{
float *f=0;
f=newarray<float>(1000000);
if(!f) return;
//use f
delete [] f;
}