Allocating 2d array of chars - c++

Constructor
This is how I'm allocating it:
char **board = new char*[width];
for(i = 0; i < width; i++){
board[i] = new char[height];
for(j = 0; j < height; j++)
board[i][j] = 0;
}
this->board = &board;
Inside the class, it's:
char ***board;
Destructor:
Now I want to delete it, so I wrote this (the board it the class field):
for(i = 0; i < width; i++)
delete (*board)[i];
delete (*board);
When running this:
Board* b = new Board(16, 30, 99);
delete b;
I get an Unhandled exception. Why?

You are storing a pointer to a variable on the stack, which becomes invalid as soon as the constructor returns. You should declare your class's data member as char **board and assign this->board = board.
EDIT: See also #Kerrek SB's comment. The local variable is redundant. Just use the data member directly (without the this->).
EDIT 2: Rectangular arrays are best created as a single array, using pointer arithmetic to index (which is what the compiler does with declared 2D arrays anyway):
char *board;
...
board = new char[width*height];
for(i = 0; i < width*height; ++i){
board[i] = 0;
}
...
char& operator()(int i, int j) { return board[width*i + j]; }
This has the advantage of requiring just one memory allocation (and therefore one delete[]). It also improves cache locality because the cells are contiguous.
Even better, if you know the dimensions at compile-time, use templates:
template <int W, int H>
class Board {
char board[W][H];
...
};
...
Board<8, 8>* b = new Board<8, 8>(...);
This requires no memory allocation at all (other than the new Board, of course).

Anything that you new you need to delete, in the exact same way:
board = new char*[width];
...
board[i] = new char[height];
...
...
delete[] board[i];
delete[] board;
No dereferencing is needed in this case.

You should use the powers of C++.
class Board
{
std::vector<std::vector<char>> board;
public:
Board(std::vector<std::vector<char>> const& board) : board(board) {}
Board(size_t x, size_t y, char val = 0)
{
std::vector<char> x2(x, val);
this->board(y, x2);
}
};
All you've got to do now is board[y].push_back(char_x_val) in order to append a new element to the end. You can treat board[y][x] just like any other 2D array (well, almost), but not worry about the deallocation.
Read up more on vectors here. (Anyone know a good tutorial?)

Related

The array in my singleton isn't keeping information after leaving a function and then it crashes when it tries to access the information again

I have an array called int **grid that is set up in Amazon::initGrid() and is made to be a [16][16] grid with new. I set every array value to 0 and then set [2][2] to 32. Now when I leave initGrid() and come back in getGrid() it has lost its value and is now 0x0000.
I don't know what to try, the solution seems to be really simple, but I'm just not getting it. Somehow the data isn't being kept in g_amazon but I could post the code.
// Returns a pointer to grid
int** Amazon::getGridVal()
{
char buf[100];
sprintf_s(buf, "Hello %d\n", grid[2][2]);
return grid;
}
int Amazon::initGrid()
{
int** grid = 0;
grid = new int* [16];
for (int i = 0; i < 16; i++)
{
grid[i] = new int[16];
for (int j = 0; j < 16; j++)
{
grid[i][j] = 0;
}
}
grid[2][2] = 32;
return 0;
}
int **grid;
g_amazon = Amazon::getInstance();
g_amazon->initGrid();
grid = g_amazon->getGridVal();
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
int index;
index = (width * 4 * i) + (4 * j);
int gridval;
gridval = grid[i][j];
lpBits[index] = gridval;
lpBits[index + 1] = gridval;
lpBits[index + 2] = gridval;
}
}
It crashes when I run it at the line where sprintf_s prints out [2][2] and it also crashes when I get to gridval = grid[i][j] because it's at memory location 0x000000.
The variable
int** grid
in the initGrid() function is a local variable. Edit** When the function returns the variable is popped off the stack. However, since it was declared with the new operator the memory still exists on the heap; it is simply just not pointed to by your global grid variable.
#Dean said in comment:
I have grid as an int** grid; in class Amazon {}; so shouldn't it stay in memory or do I need a static var.
That is the problem:
local int **grid; on Amazon::initGrid::
is masking
member int **grid; on Amazon::
as the first context has higher priority in name lookup.
So initGrid() allocates memory referenced only by a local pointer. That pointer no longer exists when you return from this function, Amazon::grid was never touched on initialization and you're also left with some bad memory issues.
So, as commented by #Remy-Lebeau, I also suggest
Consider using std::vector> or std::array, 16> instead. There is no good reason to use new[] manually in this situation.

How can return a matrix pointer in c++?

I have a big problem, i want to put a matrix pointer of objects to a function but i don't know how can do this, the objects that i use they are from derived class. This is an example of my code. Note: class Piece is a base class and class Queen is a derived class from Piece
#include "Queen.h"
void changeToQueen(Piece* mx)
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
mx[i][j] = new Queen();
}
}
}
int main()
{
Piece * matrix[7][7];
changeToQueen(matrix); // this fails
return 0;
}
You can change the input argument to void changeToQueen(Piece * mx[7][7]).
Or you can change the input argument to void changeToQueen(Piece** mx).
Change the assignment operator to mx[7*i + j] = new Queen(); and pass in the first element as input changeToQueen(&(matrix[0][0]));
The reason why both work is because multidimensional array elements are stored contiguously in memory. So all you need is a pointer to the first element.
Both solutions are a bit flawed because if you need to change the dimensions of your matrix, you have to change your code a bit. Changing your prototype to void changeToQueen(Piece** mx, size_t width, size_t height) will be helpful for the future.
Alternatively this could be a way to handle things
template <unsigned int rows, unsigned int columns>
class Board
{
public:
Board() {}
void changeToQueen()
{
for (unsigned int y = 0 ; y < rows ; ++y)
{
for (unsigned int x = 0 ; x < columns ; ++x)
{ _pieces[y][x] = Queen(); }
}
}
Piece &at(unsigned int row, unsigned int column)
{ return _pieces[row][column]; } // you should check for out of range
// you could either have a default null value for Piece to return, or throw an exception
private:
Piece _pieces[rows][columns];
};
int main()
{
Board<8,8> board;
board.changeToQueen();
// return 0; // this is not mandatory in c++
}
So, yeah, no pointers almost no worries ;)
You still want pointers?? uhm... okay maybe you could do that: Piece *_pieces[rows][columns];, i'm not sure you really need it, but I can't tell how much it would modify your existing code to do this.
First of all, I do not understand dependencies between Queen and Piece, so I suppose that Piece is super-type of Queen and assignment Piece * mx = new Queen(); is correct.
To fix the obvious problem of type mismatch you can change your
void changeToQueen(Piece* mx)
to
void changeToQueen(Piece* mx[7][7])
and with changing loops border to 7 (for (int i = 0; i < 7; i++)) or size of matrix to 8 x 8 (with the same loops) this will work.
But my suggestion is to think over method of storing data.
Perhaps you will need to build matrix of size different from 7x7, so consider the following example, where dynamic memory is used to store the matrix (in this example only Queen is used):
void changeToQueen(Queen*** &mx, int size)
{
mx = new Queen**[size]; // allocation of memory for pointers of the first level
for (int i = 0; i < size; i++)
{
mx[i] = new Queen*[size]; // allocation of memory for pointers of the second level
for (int j = 0; j < size; j++)
{
mx[i][j] = new Queen(); // allocation of memory for object
}
}
}
int main()
{
int m_size = 7;
Queen *** matrix = NULL; // now memory not allocated for matrix
changeToQueen(matrix, m_size);
return 0;
}
Note: & sign in void changeToQueen(Queen*** &mx, int size) allows to change pointer Queen *** matrix; inside the function changeToQueen

Doubling the Size of a C++ Array

The following snippet of code is my attempt to increase the size of an array by a factor of two. I am having several problems with it. Most importantly, should I be calling delete on my original array?
void enlarge(int *array, int* dbl int size) {
for (int i = 0; i < size; i++)
dbl[i] = array[i];
delete array;
array = dbl;
}
You have a few problems:
Modifying array only modifies the local copy of the pointer. You need to take a reference-to-pointer if you want the modification to be observed by the calling code.
You need to use delete[] when deleting things allocated with new[].
You attempt to copy too many items, and in so doing you overrun the original array.
void enlarge(int *& array, int size) {
// ^
// Use a reference to a pointer.
int *dbl = new int[size*2];
for (int i = 0; i < size; i++) {
// ^
// Iterate up to size, not size*2.
dbl[i] = array[i];
}
delete[] array;
// ^
// Use delete[], not delete.
array = dbl;
}
However, I would strongly suggest using std::vector<int> instead; it will automatically resize as necessary and this is completely transparent to you.
keyword double cannot be used as variable name, and previous array must be deleted before new allocation get assigned to same pointer, and loop should copy size no of items from prev array (not 2 * size)
void enlarge(int **array, int size) {
int *d = new int[size*2];
for (int i = 0; i < size; i++)
d[i] = *array[i];
delete [] *array;
*array = d;
}
if previous array was int *arr, and size is the currentsize of the array arr, call should be as: enlarge(&arr, size)

C++ pointer to int in loops?

Ok, so I'm quite new to C++ and I'm sure this question is already answered somewhere, and also is quite simple, but I can't seem to find the answer....
I have a custom array class, which I am using just as an exercise to try and get the hang of how things work which is defined as follows:
Header:
class Array {
private:
// Private variables
unsigned int mCapacity;
unsigned int mLength;
void **mData;
public:
// Public constructor/destructor
Array(unsigned int initialCapacity = 10);
// Public methods
void addObject(void *obj);
void removeObject(void *obj);
void *objectAtIndex(unsigned int index);
void *operator[](unsigned int index);
int indexOfObject(void *obj);
unsigned int getSize();
};
}
Implementation:
GG::Array::Array(unsigned int initialCapacity) : mCapacity(initialCapacity) {
// Allocate a buffer that is the required size
mData = new void*[initialCapacity];
// Set the length to 0
mLength = 0;
}
void GG::Array::addObject(void *obj) {
// Check if there is space for the new object on the end of the array
if (mLength == mCapacity) {
// There is not enough space so create a large array
unsigned int newCapacity = mCapacity + 10;
void **newArray = new void*[newCapacity];
mCapacity = newCapacity;
// Copy over the data from the old array
for (unsigned int i = 0; i < mLength; i++) {
newArray[i] = mData[i];
}
// Delete the old array
delete[] mData;
// Set the new array as mData
mData = newArray;
}
// Now insert the object at the end of the array
mData[mLength] = obj;
mLength++;
}
void GG::Array::removeObject(void *obj) {
// Attempt to find the object in the array
int index = this->indexOfObject(obj);
if (index >= 0) {
// Remove the object
mData[index] = nullptr;
// Move any object after it down in the array
for (unsigned int i = index + 1; i < mLength; i++) {
mData[i - 1] = mData[i];
}
// Decrement the length of the array
mLength--;
}
}
void *GG::Array::objectAtIndex(unsigned int index) {
if (index < mLength) return mData[index];
return nullptr;
}
void *GG::Array::operator[](unsigned int index) {
return this->objectAtIndex(index);
}
int GG::Array::indexOfObject(void *obj) {
// Iterate through the array and try to find the object
for (int i = 0; i < mLength; i++) {
if (mData[i] == obj) return i;
}
return -1;
}
unsigned int GG::Array::getSize() {
return mLength;
}
I'm trying to create an array of pointers to integers, a simplified version of this is as follows:
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
Now the problem is that the same pointer is used for j in every iteration. So after the loop:
array[0] == array[1] == array[2];
I'm sure that this is expected behaviour, but it isn't quite what I want to happen, I want an array of different pointers to different ints. If anyone could point me in the right direction here it would be greatly appreciated! :) (I'm clearly misunderstanding how to use pointers!)
P.s. Thanks everyone for your responses. I have accepted the one that solved the problem that I was having!
I'm guessing you mean:
array[i] = &j;
In which case you're storing a pointer to a temporary. On each loop repitition j is allocated in the stack address on the stack, so &j yeilds the same value. Even if you were getting back different addresses your code would cause problems down the line as you're storing a pointer to a temporary.
Also, why use a void* array. If you actually just want 3 unique integers then just do:
std::vector<int> array(3);
It's much more C++'esque and removes all manner of bugs.
First of all this does not allocate an array of pointers to int
void *array = new void*[2];
It allocates an array of pointers to void.
You may not dereference a pointer to void as type void is incomplete type, It has an empty set of values. So this code is invalid
array[i] = *j;
And moreover instead of *j shall be &j Though in this case pointers have invalid values because would point memory that was destroyed because j is a local variable.
The loop is also wrong. Instead of
for (int i = 0; i < 3; i++) {
there should be
for (int i = 0; i < 2; i++) {
What you want is the following
int **array = new int *[2];
for ( int i = 0; i < 2; i++ )
{
int j = i + 1;
array[i] = new int( j );
}
And you can output objects it points to
for ( int i = 0; i < 2; i++ )
{
std::cout << *array[i] << std::endl;
}
To delete the pointers you can use the following code snippet
for ( int i = 0; i < 2; i++ )
{
delete array[i];
}
delete []array;
EDIT: As you changed your original post then I also will append in turn my post.
Instead of
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
there should be
Array array;
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject( new int( j ) );
}
Take into account that either you should define copy/move constructors and assignment operators or define them as deleted.
There are lots of problems with this code.
The declaration void* array = new void*[2] creates an array of 2 pointers-to-pointer-to-void, indexed 0 and 1. You then try to write into elements 0, 1 and 2. This is undefined behaviour
You almost certainly don't want a void pointer to an array of pointer-to-pointer-to-void. If you really want an array of pointer-to-integer, then you want int** array = new int*[2];. Or probably just int *array[2]; unless you really need the array on the heap.
j is the probably in the same place each time through the loop - it will likely be allocated in the same place on the stack - so &j is the same address each time. In any case, j will go out of scope when the loop's finished, and the address(es) will be invalid.
What are you actually trying to do? There may well be a better way.
if you simply do
int *array[10];
your array variable can decay to a pointer to the first element of the list, you can reference the i-th integer pointer just by doing:
int *myPtr = *(array + i);
which is in fact just another way to write the more common form:
int *myPtr = array[i];
void* is not the same as int*. void* represent a void pointer which is a pointer to a specific memory area without any additional interpretation or assuption about the data you are referencing to
There are some problems:
1) void *array = new void*[2]; is wrong because you want an array of pointers: void *array[2];
2)for (int i = 0; i < 3; i++) { : is wrong because your array is from 0 to 1;
3)int j = i + 1; array[i] = *j; j is an automatic variable, and the content is destroyed at each iteration. This is why you got always the same address. And also, to take the address of a variable you need to use &

Copying from One Dynamically Allocated Array to Another C++

This seems like it should have a super easy solution, but I just can't figure it out. I am simply creating a resized array and trying to copy all the original values over, and then finally deleting the old array to free the memory.
void ResizeArray(int *orig, int size) {
int *resized = new int[size * 2];
for (int i = 0; i < size; i ++)
resized[i] = orig[i];
delete [] orig;
orig = resized;
}
What seems to be happening here is that resized[i] = orig[i] is copying values by reference rather than value, as printing orig after it gets resized returns a bunch of junk values unless I comment out delete [] orig. How can I make a deep copy from orig to resized, or is there some other problem that I am facing? I do not want to use std::vector.
Remember, parameters in C++ are passed by value. You are assigning resized to a copy of the pointer that was passed to you, the pointer outside the function remains the same.
You should either use a double indirection (or a "double pointer", i.e. a pointer to a pointer to int):
void ResizeArray(int **orig, int size) {
int *resized = new int[size * 2];
for (int i = 0; i < size; i ++)
resized[i] = (*orig)[i];
delete [] *orig;
*orig = resized;
}
or a reference to the pointer:
void ResizeArray(int *&orig, int size) {
int *resized = new int[size * 2];
for (int i = 0; i < size; i ++)
resized[i] = orig[i];
delete [] orig;
orig = resized;
}
By the way, for array sizes you should use the type std::size_t from <cstddef> - it is guaranteed to hold the size for any object and makes clear that we are dealing with the size of an object.
I highly suggest replacing the arrays with std::vector<int>. This data structure will resize as needed and the resizing has already been tested.
orig must be a pointer to a pointer to assign it to resized:
int **orig;
*orig = resized;