returning a 2D array in c++ using typecasting - c++

int** function()
{
int M[2][2] = {{1,2},{3,4}};
return (int **)M; //is this valid?
}
void anotherFn()
{
int **p = new int*[2];
for(int i = 0; i<2; i++) {
p[i] = new int[2];
}
p = function();
cout << p[0][0];
}
The above code compiled but gave runtime error. So, can I return a 2D array only if it was declared as double pointer or is there some way I can return an array as a 2D pointer?

You are representing a 2D array as a pointer to pointer to int. That is a bad idea. A better idea is to use a std::vector<std::vector<int>>. Better yet would be to use a dedicated class. But the point is that once you get rid of pointers you can return the value without any problem:
matrix_2d function() {
matrix_2d M = {{1, 2}, {3, 4}};
return M;
}
This works quite well for an appropriate definition of matrix_2d (see above).
Your code makes this whole process much more complicated by using pointers, and accesses invalid memory. In particular, you are allocating memory in your main function, but then you are discarding the pointer to that memory by reassigning it with the result of function(): inside function you aren’t using the previously-allocated memory, you are using stack-allocated memory and returning a pointer to that. Once the function exits, that stack-allocated memory is gone.

To return a 2D array, make sure you dynamically allocate it, then return the pointer. The problem with your code is that you are returning a pointer to a local variable, which will cause problems.
Basically, you'll want to do something like this (skeleton):
int** function()
{
int** M;
// Allocate M here
return M;
}

Related

Helper function to construct 2D arrays

Am I breaking C++ coding conventions writing a helper function which allocates a 2D array outside main()? Because my application calls for many N-dimensional arrays I want to ensure the same process is followed. A prototype which demonstrates what I am doing :
#include <iostream>
// my helper function which allocates the memory for a 2D int array, then returns its pointer.
// the final version will be templated so I can return arrays of any primitive type.
int** make2DArray(int dim1, int dim2)
{
int** out = new int* [dim1];
for (int i = 0; i < dim2; i++) { out[i] = new int[dim2];}
return out;
}
//helper function to deallocate the 2D array.
void destroy2DArray(int** name, int dim1, int dim2)
{
for (int i = 0; i < dim2; i++) { delete[] name[i]; }
delete[] name;
return;
}
int main()
{
int** test = make2DArray(2,2); //makes a 2x2 array and stores its pointer in test.
//set the values to show setting works
test[0][0] = 5;
test[0][1] = 2;
test[1][0] = 1;
test[1][1] = -5;
// print the array values to show accessing works
printf("array test is test[0][0] = %d, test[0][1] = %d, test[1][0] = %d, test[1][1] = %d",
test[0][0],test[0][1],test[1][0],test[1][1]);
//deallocate the memory held by test
destroy2DArray(test,2,2);
return 0;
}
My concern is this may not be memory-safe, since it appears I am allocating memory outside of the function in which it is used (potential out-of-scope error). I can read and write to the array when I am making a single small array, but am worried when I scale this up and there are many operations going on the code might access and alter these values.
I may be able to sidestep these issues by making an array class which includes these functions as members, but I am curious about this as an edge case of C++ style and scoping.
There is a difference between allocating 2D arrays like this and what you get when you declare a local variable like int ary[10][10] that based on your statement
My concern is that this operation may not be memory-safe, since it
appears that I am allocating memory for an array outside of the
function in which it is used (potential out-of-scope error)
I am guessing you do not fully understand.
You are allocating arrays on the heap. Declaring a local variable like int ary[10][10] places it on the stack. It is the latter case where you need to worry about not referencing that memory outside of its scope-based lifetime; that is, it is the following that is totally wrong:
//DON'T DO THIS.
template<size_t M, size_t N>
int* make2DArray( ) {
int ary[M][N];
return reinterpret_cast<int*>(ary);
}
int main()
{
auto foo = make2DArray<10, 10>();
}
because ary is local to the function and when the stack frame created by the call to make2DArray<10,10> goes away the pointer the function returns will be dangling.
Heap allocation is a different story. It outlives the scope in which it was created. It lasts until it is deleted.
But anyway, as others have said in comments, your code looks like C not C++. Prefer an std::vector<std::vector<int>> rather than rolling your own.
If you must use an array and are allergic to std::vector, create the 2d array (matrix) as one contiguous area in memory:
int * matrix = new int [dim1 * dim2];
If you want to set the values to zero:
std::fill(matrix, (matrix + (dim1 * dim2)), 0);
If you want to access a value at <row, column>:
int value = matrix[(row * column) + column];
Since the matrix was one allocation, you only need one delete:
delete [] matrix;

C++ returning array

I am trying to wrap my mind around arrays and pointers in C++.
I am trying to write a function that allocates memory for an int array of variable size. The array is then filled with random numbers and returned.
The problem I have is assigning values with pointers.
This is the function:
int* getArray(int length) {
int* values = new int[length];
for (int i=0; i<length; i++) {
values[i]=i;
}
return values;
}
And it works just fine.
But, if I change it to this:
int* getArray(int length) {
int* values = new int[length];
for (int i=0; i<length; i++, values ++) {
*values=i;
}
return values;
}
It doesn't work.
Can someone explain to me why I cannot do this?
This is the main method that I used to print all the values:
int main() {
int* v = getArray(100);
for(int i=0;i<100;i++, v++) {
cout << *v <<endl;
}
delete[] v;
return 0;
}
I think it is because the new operator allocates new memory in the heap and not in the stack so the pointer might actually point to the wrong direction.
But, if that is true, why is the main method working?
Side note: I do not get any kind of warning or error, but the output is just a bunch of zeros and some random numbers.
I am using the GCC compiler on Ubuntu.
values++ is modifying values, which eventually forms the function return value.
i.e. you return one past the end of the allocated array. That in itself is perfectly legal C++.
But things go very badly wrong at the function call site: you access invalid elements of the array (which very informally speaking are your "random numbers"), and calling delete[] on that is also undefined behaviour. Boom!

C++ Pointer and 2d array outputting

I'm new to C++ and still really confused about how 2d arrays work with pointers. If I have this (in example format):
int* anarray = anarrayfiller();
for (int a=0;a<10;a++) {
for (int b=0;b<10;b++) {
cout<<(char)anarray[a][b]; //Here's the error mentioned below
}
cout<<"\n";
}
//Later, outside main
int* anarrayfiller() {
int anarray[10][10];
//Populated here
return &anarray;
}
This produces an error under b in the cout<< line:
"Expression must have pointer-to-object type"
I would just check how to search through 2d arrays, and I found this:
A pointer to 2d array
Which suggests that actually this pointer points to the array of ints inside anarray[0], and if that's the case, I must be missing something in terms of returning pointers - wouldn't I then have to return a pointer to a 2d array of pointers that each points to a specific int from anarray? I'm pretty confused here. How do pointers work with 2d arrays?
You have a few errors here:
You return a pointer to a local variable. After the function returns the stack area previously occupied by that variable no longer exist, or is used by the next function.
You return a pointer to an integer, while you have a two-dimensional array. The closest would be a pointer-to-pointer.
You access thing single-pointer as though it was a double-pointer (pointer-to-pointer or pointer-to-array or array-or-arrays), but it's not. That's the reason you get errors at the pointed to line.
But you can't use pointer to pointer, as the memory layout of an array-of-arrays (a two-dimensional array) is different from a pointer-to-pointer. See e.g. this old answer of mine for an explanation of why.
This can be solved most easily by creating the array dynamically on the heap, as a pointer-to-pointer:
int **anarrayfiller()
{
int **anarray = malloc(sizeof(int *) * 10);
for (int i = 0; i < 10; ++i)
{
anarray[i] = malloc(sizeof(int) * 10);
/* Populate here */
}
return anarray;
}
As you tagged your question as C++, you should actually avoid plain arrays or pointers in favor of either std::vector (if you need to add dynamically) or std::array (if you have a fixed compile-time size):
std::array<std::array<int, 10>, 10> anarrayfiller()
{
std::array<std::array<int, 10>, 10> anarray;
// Populate arrays
return anarray;
}

How can I return a pointer to an array in C++?

Here is my simple code
arrayfunc() should store some numbers in an array, and return the pointer of this array
to main function where the content of the array would be printed
What is the problem with my code?
It only returns the pointer to the first element of the array
Any help will be appreciated.
Thanks in advance.
#include <iostream>
using namespace std;
//The definition of the function should remain the same
int* arrayfunc()
{
int *array[10];
array[0] =new int;
array[1] =new int;
array[2] =new int;
array[3] =new int;
*array[0]=10;
*array[1]=11;
*array[2]=12;
*array[3]=13;
return *array;
}
int main()
{
for(int i=0;i<4;i++)
cout<<*(arrayfunc()+i)<<endl;
return 0;
}
(1) You should allocate your array with new if you want to return it: int* array = new int[10]; [assuming here you want array of ints and not array of int*'s]
(2) to return the pointer to the first element in the array, use return array and not return *array
(3) your array is array of pointers, and not array of ints.
Your array is allocated on stack, so as soon as the function returns, it's freed. So you want to return a pointer to a dead memory.
But you are not doing that, you are just returning the valid (copy of) value of the 0th array item.
So, what you have to do:
The best idea would be to switch to stl containers. You should be using std::vector or something like that.
If you stick to the idea of manual memory management, you have to allocate the array on heap, return it from the function, and perhaps deallocate it in the caller.
Edit:
basically you want the following:
using namespace std;
vector<int> arrayfunc()
{
vector<int> v;
v.push_back(10);
...
return v;
}
...
vector<int> result = arrayfunc();
cout << result[0] << ...
This would be the right C++ way.
(Nitpicking:) You don't need to care about copying the vector, because of the RVO used by all modern C++ compilers.
Allocating an array on heap should be simple, too:
int* array = new int[4];
array[0] = 10;
...
return array;
...
int* array = arrayfunc();
...
delete[] array;
But I would strongly advise to take the former approach (with vector).
This codes seems wrong to me in several levels.
Never return an internal variable of a function. The variable array is only defined in the function, so it should never be returned outside.
Why do you allocate each int by itself with new? I would allocate the entire array at once. If you know the array length and it's constant, consider having it defined statically.
http://msdn.microsoft.com/en-us/library/s1sb61xd.aspx
Just try return array; instead of return *array;

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;
}