Initializing a two-dimensional object array in c++ - c++

I know this has been asked before (or some similar variations) however I cannot get it to work.
I am trying to create a board game that is composed of a board filled with squares. I am trying to model my board as a 2d array of Square objects. The board can be created with any width or height, and those parameters are passed in through the constructor. Here is the code I am working with:
Board.h
#ifndef BOARD_H
#define BOARD_H
#include "Square.h"
class Board{
public:
Board(int w, int h);
private:
Square **squares;
const int width;
const int height;
};
#endif
Board.cpp
#include "Board.h"
Board::Board(int w, int h):width(w), height(h) {
squares = new Square*[width];
for (int i = 0; i < width; i++) {
squares[i] = new Square[height];
}
}
However, when I try to compile this I get an error which seems to indicate the squares[i] = new Square[height] is trying to call the default constructor for the Square object (which I do not want to exist nor call in this case).
Board.cpp: In constructor ‘Board::Board(int, int)’:
Board.cpp:7:33: error: no matching function for call to ‘Square::Square()’
squares[i] = new Square[height];
Any ideas? Is this possible within C++?

Your code is equivalent to this:
struct Foo
{
Foo(int){} // no default constructor
// Foo() = default; /* uncomment this and it will work */
};
int main()
{
Foo* pFoo = new Foo[10]; // need a default ctor
delete[] pFoo;
}
The problem is that on the rhs of Foo* pFoo = new Foo[10];, you are allocating the memory as well as creating 10 Foo objects. The compiler doesn't know how to do the latter (creating the objects), as you don't provide a default constructor. To make the above code work as is, you need to specify all arguments for the non-default ctor of each object, like:
Foo* pFoo = new Foo[10]{1,2,3,4,5,6,7,8,9,0}; // this will work
The better alternative is to use std::vector instead. If you wonder why the latter works without the need for objects that don't have a default constructor, it is because it uses the placement new, and initializes the elements on demand.
Here you can see how to do it with placement new.
EDIT
The code
Foo* pFoo = new Foo[10]{1,2,3,4,5,6,7,8,9,0};
compiles in gcc, but clang fails to compile it (with -std=c++11 flag). Follow up question here.

You asked it to construct a buffer of n Squares. It tried to do so, and failed, becuase it could not construct them.
If you want memory for n squares, use new std::aligned_storage_t<sizeof(Square),alignof(Square)>[Count]. Then use placement new to construct each element in turn.
But that is a dumb idea. It is complex, opaque, and error prone.
In short, Stop managing memory manually.
vector solves this problem for you.
Create a vector of vector of squares. Or create a flat vector, and do math to find the index. It does the aligned storage bit internally, and uses placement new to construct on demand, so you do not havr to write that dangerous tricky code yourself.
Vectors let you grow them dynamically and efficiently, and replace manually managed arrays nicely. But you need to grow them from the least to the greatest element. If you do not want that, use vectors of unique ptrs to Squares, and allocate as needed (or, std::experimental::optional<Square> if you use C++17/1z compilers).
Or just use a map from pair<int,int> to Square and make it sparse. Note that you'll beed to emplace and not call [] if you want no default ctor for a Square. Again, you can use unique ptrs to Square instead of Squares directly.
There are many, many options.
Also consider having a default Square ctor: regular types are awesome.

As another answer mentioned, you could create a flat vector and do some simple arithmetic to calculate the index.
int main() {
// dimensions of the board
int width = 100;
int height = 102;
// some coordinates on the board
int x = 10;
int y = 32;
// allocate memory for every element on the board (10200 elements)
int * board = new int[width * height];
// access element (x, y) of the board
int val = board[y*width + x]
// don't forget to delete dynamic memory!
delete [] board;
}
No two distinct coordinates will have the same index.

Related

how can I copy an array from a class and double the size of the new array?

CDCatalogue::CDCatalogue() //creates array of size 4
{
maxsize=4;
numcds = 0;
cds = new CD[maxsize];
}
I want this to copy cat into a new array with double the size of cat:
CDCatalogue::CDCatalogue(const CDCatalogue& cat)
{
}
As suggested before I'd prefer to use std::vector, which offers the resize() member function for exactly what you need. This is probably what you are looking for.
If for some reason you cannot use vectors, maybe a simpler approach than having a "doubler copy constructor" would be having a function 'doubleSize' that you can call right after construct-copying.
Assuming that in your example in the question, maxsize and cds are declared as class members, you could do something like this:
CDCatalogue::doubleSize() {
unsigned int oldMaxSize = maxsize;
maxsize *= 2; // You might want to keep an eye for overflows here
CD *oldCds = cds;
cds = (CD*) new CD[maxsize];
std::copy(oldCds, oldCds+oldMaxSize, cds);
delete[] cds;
}
Note that this is not as simple as using vectors, because there is no "resize" for c++ dynamic allocations. Instead, you have to create a new array of the new desired size, copy the elements of the old array into the new, and then release the memory of the old array. Note that the last half of elements of the new array will be initialized to undefined values.

How to access a dynamically allocated matrix in c++?

I have created a dynamic matrix of class objects but i have made a big mess with handling the returned pointers.
My intention is to create a matrix of class Point( Int x,Int y) and later to use it in different ways in the program.
Everything is working but i can't figure out the returned pointers game between the functions.
class Point
{
private:
int x;
int y;
public:
Point(int x,int y);
void SetPoint(int x,int y);
};
In a second class I use a Point object as class member.
Init_Pallet() is used to Initialize the Matrix.
class Warehouse
{
private:
Robot r1,r2;
Point *Pallet_Matrix;
public:
Point* Init_Pallet();
};
This is the Init function
Point* Warehouse::Init_Pallet()
{
int rows =10,cols =10;
Point** Pallet_Matrix = new Point*[rows];
for (int i = 0; i < rows; i++)
Pallet_Matrix[i] = new Point[cols];
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; j++) //Pallet matrix Init, x point for robots amount in position and y for box amount
Pallet_Matrix[i][j].SetPoint(0,0);
return *Pallet_Matrix;
}
The Init function is called by WareHouse C'Tor (ignore the other vars)
Warehouse::Warehouse(Robot p_r1,Robot p_r2): r1(p_r1),r2(p_r2)
{
this->r1=p_r1;
this->r2=p_r2;
Point *p =Init_Pallet();
this->Pallet_Matrix=p;
}
My question is: How do I return the address to the beginning of the matrix from the Init function to the C'Tor who called it?
And second question: how do i access the matrix different locations in the format of Matrix[i][j] after returning the matrix adress to the C'Tor.
Thank you in advance for all the help and your time.
You should just have Init_Pallet return a Point** and then do return Pallet_Matrix;. Currently you're copying one of the Point*s that you allocated out of the function, so the copy is no longer part of a contiguous array that you can index.
Don't forget to delete[] the dynamically arrays in your destructor.
However, you should much prefer to use the standard library containers like std::array or std::vector. Then you don't need to worry about the dynamic allocation yourself and no pointers to get in a mess with.
If I were doing it, I would just have:
class Warehouse
{
public:
Warehouse() : Pallet_Matrix() { }
private:
Robot r1,r2;
std::array<std::array<Point, 10>, 10> Pallet_Matrix;
};
And that's it. No init needed. No dynamic allocation. No assigning 0 to every element (if you give Point a default constructor that zero-initialises). Done.
How do I return the address to the beginning of the matrix from the Init function to the C'Tor?
In case you would really need just an address of first element, pretty straightforward would be:
return &Pallet_Matrix[0][0];
how do i access the matrix different locations in the format of Matrix[i][j] after returning the matrix address
Init_Pallet is a member function, which could simply work with the Pallet_Matrix member directly. Otherwise, the Init_Pallet function could actually return Point**, which should however make you feel that something's wrong with this code.
Better[1] solution would be:
Define the default constructor for Point:
class Point
{
public:
Point() : x(0), y(0){}
...
Use std::vectors instead of dynamically allocated arrays:
class Warehouse
{
private:
std::vector< std::vector<Point> > Pallet_Matrix;
and instead of:
Point *p =Init_Pallet();
this->Pallet_Matrix=p;
you would simply use std::vector's constructor:
int rows = 10, cols = 10;
Pallet_Matrix = std::vector< std::vector<Point> >(rows, cols);
[1] Better = You don't want to handle the memory management on your own.
The problem is that the returned type of Init_Pallet() is wrong — its a row, not a matrix. And in the last line of Warehouse::Init_Pallet() you dereference the proper pointer to matrix obtaining the pointer to the first row of the matrix.
You need to write Point **Pallet_Matrix; in Warehouse, use Point** Warehouse::Init_Pallet() definition of Init_pallet(), and return Pallet_Matrix in the last line of Init_Pallet().
The notation Point *row means the row is "the array of points" or "the pointer to the beginning of the array of points". The notation Point **matrix means the matrix is "the array of pointers to the beginnings of the arrays of points" or "the pointer to the beginning of such an array".
First: are the dimensions really constant, or is this just an
artifact of your having simplified the code for posting? If
they are really constant, there's no need for dynamic
allocation: you can just write:
Point palletMatrix[10][10];
and be done with it. (If you have C++11, it's even better; you
can use std::array, and palletMatrix will have full object
semantics.)
If you do need dynamic indexes, the only reasonable way of
doing this is to write a simple matrix class, and use it:
class Matrix
{
int m_rows;
int m_columns;
std::vector<Point> m_data;
public:
Matrix( int rows, int columns )
: m_rows( rows )
, m_columns( columns )
, m_data( rows * columns, Point( 0, 0 ) )
{
}
Point& operator()( int i, int j )
{
return m_data[ i * m_columns + j ];
}
// ...
};
Trying to maintain a table of pointers to tables is not a good
solution: it's overly complex, it requires special handling to
ensure that each row has the same number of columns, and it
generally has poor performance (on modern machines, at least,
where locality is important and multiplication is cheap).
Note too that the actual data is in an std::vector. There are
practically no cases where a new[] is a good solution; if you
didn't have std::vector (and there was such a time), you'd
start by implementing it, or something similar. (And
std::vector does not use new[] either.)
EDIT:
One other thing: if you're putting Point in a matrix, you might
want to give it a default constructor; this often makes the code
simpler.

Error when allocating a two dimentional array of an Object in C++

I am building a class called ParticleMatrix that stores a two dimensional array of the object Ball. I want to dynamically allocate space for them. The code looks like this.
/*
* allocateParticle takes a width w, height h, restlength RL then allocates space for
* and constructs a 2D array of Particles of subclass Ball.
*/
void ParticleMatrix::allocParticles(int w, int h, float RL)
{
// Gets the number of particles in the xDirection
xPart = getNrPart(w,RL);
// Gets the number of particles in the yDirection
yPart = getNrPart(h,RL);
// Allocates a row of pointers to pointers.
ballArray = new Ball*[xPart];
// The ID of the particles.
int ID = 0;
// For every particle in the xDirection
for(int x = 0; x<xPart; x++)
{
// Allocate a row of Ball-pointers yPart long.
ballArray[x] = new Ball[yPart];
// For every allocated space
for(int y = 0; y<yPart; y++)
{
// Construct a Ball
ballArray[x][y] = Ball( ID, RL*(float)x, RL*(float)y);
ID++;
}
}
}
The problem occurs with the line "ballArray[x] = new Ball[yPart]". CodeBlocks gives me the compiler error " error: no matching function for call to 'Ball::Ball()' ".
I have 4 constructors for Ball with different signatures, none looking like: "Ball()".
I have tried with adding a constructor "Ball::Ball()" and it compiles then but I feel like I should be able to just allocate space for an object and later instantiate them.
What I'm wondering is: Why can't I allocate space for the object Ball without having a constructor "Ball::Ball()" in the code above?
and: If it is possible in some way to allocate space without the constructor "Ball::Ball()", how would I go about doing it?
I know I can create the constructor "Ball::Ball()" and give the objects some dummy values then later set them to their required values, but I feel uncomfortable doing this since I don't know why I couldn't just "Allocate space -> instantiate object". I hope I was able to explain my issue. Thanks!
Instead of new T, that gets memory and calls ctor, you can call operator new with a size you supply. The only provides you memory and nothing else. Then you can call placement new on properly calculated locations, that will invoke only your ctor. On the location you posted instead of allocating anew. Search google for the provided terms to see examples.
But normally you're not supposed to do any of that, your task can be done well using a std::vector<Ball> with way less effort and more security.
Another "C++ way" of doing this is using std::allocator.
It provides you allocate and deallocate which only reserve memory without constructing elements.
std::allocator<Ball*> ball_ptr_allocator;
std::allocator<Ball> ball_allocator;
Ball ** ptr = ball_ptr_allocator.allocate(10);
for (size_t x=0; x<10; ++x)
{
ptr[x] = ball_allocator.allocate(10);
for (size_t y=0; y<10; ++y)
{
ball_allocator.construct(&ptr[x][y], ID, RL*(float)x, RL*(float)y);
// if you do not have access to C++11 use this:
// ball_allocator.construct(&ptr[x][y], Ball(ID, RL*(float)x, RL*(float)y));
++ID;
}
Note several issues here:
I'd generally suggest to use unsigned types for sizes (like size_t for example).
If you make the allocator a member you can access is in the destructor etc. to deallocate stuff again. std::allocator<Ball> m_ballAlloc;
You have to (somehow) keep track of the constructed elements and allocated memory. If one of the constructions will throw an exception you should be able to clean up the constructed elements and deallocate the allocated memory.
For the deallocation tracking you can go with an additional loop in your allocParticles
for(size_t x = 0; x<xPart; x++) ballArray[x] = nullptr;
Now you know that every ballArray[i] that is not a nullptr needs to be deallocated.
But you'll have to destroy your elements first.
If you make your ID a member variable of the class you can use it to destroy constructed elements (since it's only incremented after element construction).
I wrote a destructor example with respect to ballArray destruction only, note that you'll may have to take care of other resources, too, if present.
~ParticleMatrix (void)
{
// check this here and set ballArray to nullptr upon construction
// of the ParticleMatrix
if (ballArray != nullptr)
{
// start to destroy the Balls
size_t destroycounter(0U);
for(size_t x = 0; x<xPart; x++)
{
for(size_t y = 0; y<yPart; y++)
{
if (destroycounter < ID)
{
m_ballAlloc.destroy(&ballArray[x][y]);
++destroycounter;
}
}
}
// deallocate 2nd dimension arrays
for(size_t x = 0; x<xPart; x++)
{
if (ballArray[x] != nullptr) m_ballAlloc.deallocate(ballArray[x], yPart);
}
// deallocate first dimension
delete [] ballArray;
}
}
In C++, the operator new does not just allocate space for a variable, but also constructs it. If you don't have a default construtor Ball::Ball(), then you cannot construct each object in the array. There is no "just allocate space" in C++, in principle...

Using a constructor for an array of structures

I want to create an array of structures. The structure uses a constructor as shown below:
struct struct_seedinfo {
struct_seedinfo(const mxArray *prhs[ ],const int seed_id){
mxArray *mat_coords, *mat_defvectorinit, *mat_corrcoef, *mat_roi_id;
mat_coords = mxGetField(prhs[1],seed_id,"coords");
coords = mxGetPr(mat_coords);
mat_defvectorinit = mxGetField(prhs[1],seed_id,"defvectorinit");
defvectorinit = mxGetPr(mat_defvectorinit);
mat_corrcoef = mxGetField(prhs[1],seed_id,"corrcoef");
corrcoef = *(mxGetPr(mat_corrcoef));
mat_roi_id = mxGetField(prhs[1],seed_id,"roi_id");
roi_id = *(mxGetPr(mat_roi_id));
}
double *coords;
double *defvectorinit;
double corrcoef;
double roi_id;
static int num_seeds;
};
How could I create an arbitrary sized array of this structure? I need to allocate memory for it, but it seems like I would need to allocate memory without calling the constructor, and then call the constructor later in a forloop. Is there a good or preferred way of doing this? Thanks.
You can do std::vector<struct_seedinfo>. This will create an array and it will automagically increase in size when needed.
You'll also need to overload the copy constructor and copy-assignment operator for your struct to be able to be used in a vector. You need a destructor too. This is called the Rule of Three in C++
Well since the size stay constant, you can use the following solution :
*This assumes your ok with defining a default constructor.
First declare a default constructor in your class.
struct_seedinfo(){
//If you want to initlaize something.
}
Than you can use the following to create you array :
struct_seedinfo * arr = new struct_seedinfo[size_of_array];
And then you need for each space to do your specific build :
arr[i] = struct_seedinfo(//arguments);
This is if you badly need an array, i do also think the vector solution is better.

The right way to create pointer to pointer object?

What is the right way to create a pointer to pointer object? Like for example,
int **foo;
foo = new int[4][4];
Then the compiler gives me an error saying "cannot convert from int (*)[4] to int **.
Thanks.
int **foo = new int*[4];
for (int i = 0; i < 4; i++)
foo[i] = new int[4];
Clarification:
In many languages the code above is called a jagged array and it's only useful when the "rows" have different sizes. C++ has no direct language support for dynamically allocated rectangular arrays, but it's easy to write it yourself:
int *foo = new int[width * height];
foo[y * height + x] = value;
Using raw new is a bit unwieldy to use. The inner dimension (last 4) must be a compile time constant, in addition. You also have to remember to delete the array once you are finished using it.
int (*foo)[4] = new int[4][4];
foo[2][3] = ...;
delete[] foo;
If that feels too "syntactic braindead", you can use typedef to prettify it
typedef int inner_array[4];
inner_array *foo = new int[4][4];
foo[2][3] = ...;
delete[] foo;
That's called a rectangular 2-dimensional array, because all the rows (4 of them, which can be determined at runtime) have the same width (which must be known at compile time).
Alternatively, use std::vector, with which you don't need to mess around with delete anymore, and which will also handle the raw pointer mess:
std::vector<int> v(4 * 4);
v[index] = ...;
You may later add or remove integers from the vector as you wish. You could also create a vector< vector<int> >, but i find it unwieldy to use, because you have to manage the separate row-vectors (which can be of varying lengths), and they are not seen as "one unit" together.
You can always create a function that maps a two dimensional coordinate to a one-dimensional index
inline int two_dim(int x, int y) {
return y * 4 + x;
}
v[two_dim(2, 3)] = ...;
For a simple two-dimensional array whose size you know beforehand, you don't need new at all, though
int x[4][4];
x[2][3] = ...;