how to return two dimensional char array c++? - c++

i ve created two dimensional array inside a function, i want to return that array, and pass it somewhere to other function..
char *createBoard( ){
char board[16][10];
int j =0;int i = 0;
for(i=0; i<16;i++){
for( j=0;j<10;j++){
board[i][j]=(char)201;
}
}
return board;
}
but this keeps giving me error

Yeah see what you are doing there is returning a pointer to a object (the array called board) which was created on the stack. The array is destroyed when it goes out of scope so the pointer is no longer pointing to any valid object (a dangling pointer).
You need to make sure that the array is allocated on the heap instead, using new. The sanctified method to create a dynamically allocated array in modern C++ is to use something like the std::vector class, although that's more complicated here since you are trying to create a 2D array.
char **createBoard()
{
char **board=new char*[16];
for (int i=0; i<16; i++)
{
board[i] = new char[10];
for (int j=0; j<10; j++)
board[i][j]=(char)201;
}
return board;
}
void freeBoard(char **board)
{
for (int i=0; i<16; i++)
delete [] board[i];
delete [] board;
}

The best approach is create a board class and make the ctreateBoard function its constructor:
class Board {
private:
char mSquares[16][10];
public:
Board() {
for(int i=0; i<16;i++){
for( int j=0;j<10;j++){
mSquares[i][j]=201;
}
}
// suitable member functions here
};
For information on how to use such a class, there is no substitute for reading a good book. I strongly recommend Accelerated C++ by Andrew Koenig and Barbra Moo.

This approach will not work. If you return a pointer to a local variable you'll run into undefined behaviour. Instead allocate an array on heap with new and copy data into it manually indexing it.

I would really recommend using STL vector<> or boost/multi_array containers for this.
If you must use arrays, then I would recommend using a typedef to define the array.
typedef char[16][10] TBoard;
You could also return
char**
...but then you would need to typecast it to the correct size in order to index it correctly. C++ does not support dynamic multiple dimension arrays.
Also as others have suggested you can't return an object on the stack (i.e., local variable)

Don't return pointer to a local variable, as other mentioned. If I were forced to do what you want to achieve, first I'd go for std::vector. Since you haven't learnt std::vector, here is another way:
void createBoard(char board[16][10])
{
int j =0;int i = 0;
for(i=0; i<16;i++){
for( j=0;j<10;j++){
board[i][j]=(char)201;
}
}
}

You should return char** instead of char*

The simple answer to your question is char**.
Having said that, DON'T DO IT !
Your "board" variable won't last outside createBoard().
Use boost::multi_array and pass it as a reference to createBoard() or return it directly (but if you do that, it will be copied).

You must not return a pointer to a functions local variables because this space gets overwritten as soon as the function returns.
The storage associated with board is on the function's stack.

Related

Do all arrays in C++ classes have to be dynamically allocated, or just their member variables?

For an assignment, I had to separate some code for Conway's Game of Life into multiple files, but now I'm trying to get a deeper understanding of why the code was written the way it was. I have a class, World, and part of the constructor for that class looks like this:
world.h:
class World {
public:
// Constructor/destructor
World();
~World();
void updateWorld();
...
private:
char **m_grid_1;
char **m_grid_2;
...
};
world.cpp:
World::World()
{
m_toggle = true;
m_grid_1 = new char*[MAX_ROWS];
m_grid_2 = new char*[MAX_ROWS];
for (int i = 0; i < MAX_ROWS; i++) {
m_grid_1[i] = new char[MAX_COLS];
m_grid_2[i] = new char[MAX_COLS];
}
...
}
MAX_ROWS and MAX_COLS are globals that live in a header now.
Arrays have always kind of confused me, so these questions might seem kind of basic:
What does char** mean in the context of the member variable m_grid_1 or m_grid_2? Pointer to a pointer of chars? Those members are 2D arrays, so I'm not sure why pointers are used here instead.
Why is new used here in combination with that loop in the constructor? Couldn't you just say m_grid_1[MAX_ROWS][MAX_COLS];?
Also, rather than toggle between the two grids, if I wanted to make a local copy of m_grid_1 in the member function updateWorld() and use that local copy to get the next state of the game, would I need to use new? This is what I have now, and it seems to work, but I'm not sure if I'm doing something wrong by not dynamically allocating the 2D array here:
void World::updateWorld() {
char grid_copy[MAX_ROWS][MAX_COLS];
for (int i = 0; i < MAX_ROWS; i++) {
for (int j = 0; j < MAX_COLS; j++) {
grid_copy[i][j] = m_grid_1[i][j];
}
}
// loop over grid_copy to find next state of m_grid_1
}
Do all arrays in C++ classes have to be dynamically allocated?
Not in general.
or just their member variables?
Member variables don't have to be allocated dynamically either.
What does char** mean ... Pointer to a pointer of chars?
It is a pointer to pointer to char.
Those members are 2D arrays
Correction: Those members are pointers. They used pointers, therefore they are not arrays.
Why is new used here in combination with that loop in the constructor?
Because the author of the program chose to use it.
Couldn't you just say m_grid_1[MAX_ROWS][MAX_COLS];?
Maybe. If MAX_ROWS and MAX_COLS are compile time constant and if they are small, then sure.
If I wanted to make a local copy of m_grid_1 in the member function updateWorld() and use that local copy to get the next state of the game, would I need to use new?
If the question is whether you need dynamic allocation, then maybe. See the answer above.
There is hardly ever need to use new. A simpler and safer way to create a dynamic array is to use std::vector.

Return 2d array from C++

Inside a function, I make a 2d array that fills itself from a text file and needs to get returned to main. The array stays a constant size through the whole program.
I know this is something that gets asked a lot, but I always seem to get one of two answers:
Use std::vector or std::array or some other STD function. I don't really understand how these work, is there any site actually explaining them and how they act compared to normal arrays? Are there any special #includes that I need?
Or
Use a pointer to the array, and return the pointer. First, on some of the answers to this it apparently doesn't work because of local arrays. How do I tell when it does and doesn't work? How do I use this array back in the main function?
I'm having more trouble with the concept of pointers and std::things than with the actual code, so if there's a website you know explains it particularly well, feel free to just put that.
Not necessarily the best solution, but the easiest way to get it working with vectors. The advantages are that you don't need to delete memory (happens automatically) and the array is bounds-checked in debug mode on most compilers.
#include <vector>
#include <iostream>
using array2D = std::vector< std::vector< int > >;
array2D MyFunc(int x_size, int y_size)
{
array2D array(y_size, vector< int >(x_size));
int i = 0;
for (int y = 0; y < array.size(); y++)
{
for (int x = 0; x < array[y].size(); x++)
{
// note the order of the index
array[y][x] = i++;
}
}
return array;
}
int main()
{
array2D bob = MyFunc(10, 5);
for (int y = 0; y < bob.size(); y++)
{
for (int x = 0; x < bob[y].size(); x++)
{
cout << bob[y][x] << "\n";
}
}
}
Live example:
http://ideone.com/K4ilfX
Sounds like you are new to C++. If this is indeed the case, I would suggest using arrays for now because you probably won't be using any of the stuff that STL containers give you. Now, let's talk about pointers.
You are correct that if you declare a local array in your function, the main function won't have access to it. However, this is not the case if you dynamically allocate the array using the new keyword. When you use new to allocate your array, you essentially tell the compiler to reserve a chunk of memory for your program. You can then access it using a pointer, which is really just the address of that chunk of memory you reserved. Therefore, instead of passing the entire array to the main function, all you need to do is pass a pointer (address) to that array.
Here are some relevant explanations. I will add to them as I find more:
Dynamic Memory
The easiest way to create a 2d array is as follows:
char (*array)[10];
array = new array[5][10];
Two dimensional arrays can be tricky to declare. The parenthesis above in the variable declaration are important to tell the compiler array is a pointer to an array of 10 characters.
It is really essential to understand pointers with C and C++ unless using the std:: collections. Even then, pointers are widely prevalent, and incorrect use can be devastating to a program.

Filling up a vector of pointers

please excuse my noobie question..
I have :
class A;
{
public:
A(int i) : m_i(i) {}
int m_i;
}
A newA(i);
{
return A(i);
}
And I want to fill the following vector, but using a loop where an object A is created with a function (newA):
vector<A*> list;
for (int i=0 ; i<3; ++i) { A a = newA(i); list.push_back(&a); }
That works if I use a vector<A> but not with a vector<A*> since all I do is changing the value at &a and pushing 3 times the same pointer &a.
How can I do so that I create a new A every time, and not change the value of the same pointer.
I came up with the following but I hope it's not the only way, since it includes dynamic allocation..
A newA(i);
{
return A(i);
}
vector<A*> list;
for (int i=0 ; i<3; ++i)
{
A a = newA(i);
list.push_back(new A(a));
}
Note that class A is actually huge in memory, hence the pointers.
You should realize the first method is bad:
for (int i=0 ; i<3; ++i) { A a = newA(i); list.push_back(&a); }
You are creating a local object and then storing a pointer to it. Once you leave the loop the object will not exist anymore and you have undefined behavior. As john said there is no sensible way to do what you want to do without using dynamic allocation. As Billy noted instead of using a raw pointer you can use a shared_ptr or unique_ptr and then you don't have to worry about memory management which is possibly why you want to avoid dynamic allocation.
Storing a vector of pointers does not give the vector ownership of the resulting instances of A. There is going to be dynamic allocation involved in order to populate such a structure.
(Of course, in real code you should probably create a vector<unique_ptr<T>> or a vector<shared_ptr<T>> instead of a vector<T*> but that's another topic)
It is the only way, as in your first example the object that you store the pointer to is immediately destroyed at each iteration of the for loop, as it goes out of scope.

Filling an array of pointers, deleting when exiting

In C++, Lets say I'm creating an array of pointers and each element should point to a data type MyType. I want to fill this array in a function fillArPtr(MyType *arPtr[]). Lets also say I can create MyType objects with a function createObject(int x). It works the following way:
MyType *arptr[10]; // Before there was a mistake, it was written: "int *arptr[10]"
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
Is it the best way to do it? In this program how should I use delete to delete objects created by "new" (or should I use delete at all?)
Since you asked "What is the best way", let me go out on a limb here and suggest a more C++-like alternative. Since your createObject is already returning objects by value, the following should work:
#include <vector>
std::vector<MyType> fillArray()
{
std::vector<MyType> res;
for (size_t i = 0; i != 10; ++i)
res.push_back(createObject(i));
return res;
}
Now you don't need to do any memory management at all, as allocation and clean-up is done by the vector class. Use it like this:
std::vector<MyType> myArr = fillArray();
someOtherFunction(myArr[2]); // etc.
someLegacyFunction(&myArr[4]); // suppose it's "void someLegacyFunction(MyType*)"
Do say if you have a genuine requirement for manual memory management and for pointers, though, but preferably with a usage example.
Your method places the array of pointers on the stack, which is fine. Just thought I'd point out that it's also possible to store your array of pointers on the heap like so. Youd do this if you want your array to persist beyond the current scope
MyType **arptr = new MyType[10];
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
If you do this, don't forget to delete the array itself from the heap
for ( int i = 0 ; i < 10 ; i++ ) {
delete arptr[i];
}
delete [] arptr;
If you're going to use vector, and you know the size of the array beforehand, you should pre-size the array. You'll get much better performance.
vector<MyType*> arr(10);
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
I suggest you look into boost shared_ptr (also in TR1 library)
Much better already:
std::vector<MyType*> vec;
for (int i=0; i<10; i++)
vec.push_back(new MyType(createObject(i));
// do stuff
// cleanup:
while (!vec.empty())
{
delete (vec.back());
vec.pop_back();
}
Shooting for the stars:
typedef boost::shared_ptr<MyType> ptr_t;
std::vector<ptr_t> vec;
for (int i=0; i<10; i++)
vec.push_back(ptr_t(new MyType(createObject(i)));
You would basically go through each element of the array and call delete on it, then set the element to 0 or null.
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
Another way to do this is with an std::vector.
Use an array of auto_ptrs if you don't have to return the array anywhere. As long as you don't make copies of the auto_ptrs, they won't change ownership and they will deallocate their resources upon exiting of the function since its RAII based. It's also part of the standard already, so don't need boost to use it :) They're not useful in most places but this sounds like a good one.
You can delete the allocated objects using delete objPtr. In your case,
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
The rule of thumb to remember is, if you allocate an object using new, you should delete it. If you allocate an array of objects using new[N], then you must delete[] it.
Instead of sticking pointers into a raw array, have a look at std::array or std::vector. If you also use a smart pointer, like std::unique_ptr to hold the objects within an std::array you don't need to worry about deleting them.
typedef std::array<std::unique_ptr<MyType>, 10> MyTypeArray;
MyTypeArray arptr;
for( MyTypeArray::iterator it = arptr.begin(), int i = 0; it != arptr.end(); ++it ) {
it->reset( new MyType( createObject(i++) ) );
}
You don't need to worry about deleting those when you're done using them.
Is the createObject(int x) function using new to create objects and returning a pointer to this?. In that case, you need to delete that as well because in this statement
new MyType( createObject(i++) )
you're making a copy of the object returned by createObject, but the original is then leaked. If you change createObject also to return an std::unique_ptr<MyType> instead of a raw pointer, you can prevent the leak.
If createObject is creating objects on the stack and returning them by value, the above should work correctly.
If createObject is not using new to create objects, but is creating them on the stack and returning pointers to these, your program is not going to work as you want it to, because the stack object will be destroyed when createObject exits.

How do I return an array from a function?

I don't get a error message when I compile the code but I cant a proper result.
#include <iostream>
using namespace std;
struct Coord{
int r;
int c;
};
struct CoordwValue{
Coord C;
char Value;
};
CoordwValue* getNeighbors();
int main (){
CoordwValue *k= getNeighbors();
for (int i=0;i<4;i++)
cout<<(k[i].Value);
}
CoordwValue *getNeighbors(){
CoordwValue Neighbors[4];
Neighbors->Value='X';
Neighbors->C.r= 0;
Neighbors->C.c= 1;
(Neighbors+1)->Value='0';
(Neighbors+1)->C.r= 1;
(Neighbors+1)->C.c= 2;
(Neighbors+2)->Value='1';
(Neighbors+2)->C.r= 2;
(Neighbors+2)->C.c= 1;
(Neighbors+3)->Value='X';
(Neighbors+3)->C.r= 1;
(Neighbors+3)->C.c= 0;
//for (int i=0;i<4;i++)
// cout<<Neighbors[i].Value;
return Neighbors;
}
This part of the code prints X01X
for (int i=0;i<4;i++)
cout<<Neighbors[i].Value;
But I can't get the same result from
for (int i=0;i<4;i++)
cout<<(k[i].Value);
What is the problem?
Edit:
This version of the code works fine.
#include <iostream>
using namespace std;
char* getNeighbors();
int main (){
char *k= getNeighbors();
for (int i=0;i<4;i++)
cout<<(*(k+i));
}
char *getNeighbors(Coord C, int r){
char Neighbors[4];
*Neighbors='X';
*(Neighbors+1)='0';
*(Neighbors+2)='1';
*(Neighbors+3)='X'
return Neighbors;
}
You are returning a pointer to a stack-allocated array. This array will cease to exist when the function returns, so the pointer will effectively be invalid though it may still work (until you call another function, such as cout, when it will probably be wiped out by the new stack segment). You probably want to say this:
CoordwValue *Neighbors = new CoordwValue[4];
Instead of this:
CoordwValue Neighbors[4];
Of course, then it's up to the calling function (main in this case) to properly delete[] the array when it is finished using it.
If you want to return an array of four objects, you don't necessarily need to use dynamic allocation or std::vector. You just need to wrap the array in a class so that you can return it. For example:
struct GetNeighborsResult
{
CoordwValue Value[4];
};
GetNeighborsResult getNeighbors();
Boost, TR1, and C++0x all have a container-like array class template that you can easily use for this purpose:
std::array<CoordwValue, 4> getNeighbors();
The advantage of using array is that you don't have to write a separate class for every type and number that you have, you can just use the class template.
If you do choose to return a pointer to a dynamically allocated array, use a smart pointer to manage the memory. There is no reason whatsoever to not use a smart pointer.
Returned array is created on the stack and returned. I'd suggest to read about difference of heap and stack memory here.
If array needs to be returned from a function you have an option of allocating memory dynamically using new. However, then the memory must be released with delete or it will result in a memory leak.
STL containers use dynamic memory and have overloaded copy constructor. Replacing array with vector<T> will allow you to return the values safely.
The problem is that you are returning a variable on the stack. The variable Neighbors is created in on the stack in the method getNeighbors. When you leave this method, the memory is destroyed, corrupting your return value.
How to fix it? Pass in an array created on the outside and fill the values in.
You are returning the address of a local variable. When getNeighbors returns, Neighbors[4] goes out of scope, causing all sorts of problems, including what should be a compiler warning/error.
You have a couple of options around this: first, do what cdhowie said and return a dynamically allocated array. Another is to return by value, so the return is a COPY of Neighbors[4], not a pointer to it. I think the syntax for this would be something like CoordwValue getNeighbors()[4] { .... }
Yet another is to have the caller pass in a pre-allocated array that you fill in.