2D Array of Pointers -> Classes - c++

I am having problems with my constructor in class World.
I created a 2D array with pointers where each entry in the array is of type Organism, hence the line of code:
Organism* grid[20][20];
When I run my program, I only see
hello
and after that, I get a message saying that my program has stopped working. I'm pretty sure it's the line of code
grid[i][j]->symbol = ' ';
that's causing the problem. Just to see what would happen, I changed that line to
grid[i][j];
and didn't get any errors. But, the moment I put ->, I seem to get errors.
Is there a reason why my program stops working after I put ->? Any help would be appreciated.
This is my code:
#include <iostream>
using namespace std;
class Organism
{
public:
char symbol;
};
class World
{
public:
World();
private:
Organism* grid[20][20];
};
int main()
{
World world;
return 0;
}
World::World()
{
for(int i = 0; i < 20; i++)
for(int j = 0; j < 20; j++)
{
cout << "hello" << endl;
grid[i][j]->symbol = ' ';
cout << "here" << endl;
}
}

You have an array of pointers to Organism.
Pointers can not hold any data other than an address. They can only point to memory (that holds data).
Your array's pointers does not point to anything, thats why you get undefined behaviour when you try to assign data to where the pointers point at.
You need to allocate memory for your array.
Organism grid[20][20]; // Create an array of objects (not pointers).
/* ... */
grid[i][j].symbol = ' ';
Same using dynamic memory:
class World {
public:
World();
~World(); // Rule of Three.
World(const World&) = delete; // Rule of Three.
World& operator=(const World&) = delete; // Rule of Three.
private:
Organism** grid;
};
World::World() {
grid = new Organism*[20]; // Allocate memory to point to.
for(std::size_t i = 0; i != 20; ++i) {
grid[i] = new Organism[20]; // Allocate memory to point to.
for(std::size_t j = 0; j != 20; ++j) {
cout << "hello" << endl;
grid[i][j].symbol = ' ';
cout << "here" << endl;
}
}
}
// Destructor needed to deallocate memory (otherwise it will leak).
World::~World()
{
for (std::size_t i = 0; i != 20; ++i) {
delete[] grid[i];
}
delete[] grid;
}
Now you can see how complicated it gets when using dynamic memory and why it's recommended to prefer to use automatic storage duration (i.e. create objects, not pointers and new/delete).
Even better is to use a container from the standard library for storing your elements as e.g. std::vector.
Related:
What is The Rule of Three?

Change
Organism* grid[20][20];
To
Organism grid[20][20];
and use
grid[i][j].symbol = '';
instead of
grid[i][j]->symbol = '';
and add a default constructor to Organism
class Organism
{
Organism();
...
}
or make Organism a struct
struct Oranism
{
...
}

Related

How to initialize an array that is private in a class using constructor at runtime?

I have made a class Graph when I have made a pointer in private access in the class named visited. In the constructor I have initialized the array with zero at all places but when I am checking if all the values are zero in another method ,It is showing garbage values in the array but when I print it in the constructor itself then it showing all zeroes.
#include<iostream>
#include<vector>
#include<list>
using namespace std;
class Graph {
private:
int vertices,edges;
vector <list<int>> graph;
vector <int> vs;
int *visited;
public:
Graph (int vertices)
{
this->vertices = vertices;
list <int>l;
for (size_t i = 0; i < vertices; i++) {
graph.push_back(l);
vs.push_back(i);
}
edges=0;
// ####### made a new array, initialized all values with zeroes and assigned it to the instance variable visited #########
int a[vertices]={0};
this->visited = a;
// ######## in the constructor it is showing correct values below #######
for (size_t i = 0; i < vertices; i++) {
std::cout << this->visited[i] << ' ';
}
std::cout << '\n';
}
virtual ~Graph ()
{
}
void showList()
{
// just printing the graph in the form of adjacency list
// it is working fine
for (size_t i = 0; i < vertices; i++)
{
list <int>::iterator p = graph[i].begin();
std::cout << i ;
for (; p != graph[i].end() ; p++)
{
std::cout << " -> " << *p ;
}
std::cout << " -> NULL" << '\n';
}
// ######## when I am checking the values here then it is printing garbage values
for (size_t i = 0; i < this->vertices; i++) {
std::cout << this->visited[i] << ' ';
}
}
void addEdge(int source, int destination)
{
graph[source].push_back(destination);
}
};
int main()
{
Graph g(6);
g.addEdge(0,1);
g.addEdge(0,2);
g.addEdge(1,0);
g.addEdge(1,3);
g.addEdge(1,4);
g.addEdge(2,0);
g.addEdge(2,4);
g.showList();
return 0;
}
when i call the showList method the it should print the adjacenct list and all zeroes(contents of array named visited)
I have made a class Graph.
Yes you have.
class Graph {
I have made a pointer in private access in the class named visited.
Yes you have.
private:
int *visited;
In the constructor I have initialized the array with zero at all places.
Yes you have.
int a[vertices]={0};
But I would note that this is a variable that is local to the constructor. It is not visible to any other methods. Also when the constructor finishes the lifespan of this object ends. Any attempt to accesses this array after its lifetime ends is undefined behavior. So accessing this by some sneaky mechanism (like savings its address in a pointer) is going to cause bad things to happen.
Here you are doing something sneaky (and very bad):
this->visited = a;
but when I am checking if all the values are zero in another method
You are accessing the array through a pointer visited. This is pointing to an array that no longer exists because the array is local to another function.
std::cout << this->visited[i] << ' '; // This is broken code.
It is showing garbage values in the array
You are very unlucky. It would have been nicer if the program had crashed and made it more obvious that something bad is happening. Unfortunately you have discovered that undefined behavior can do anything (including simply return some random values).
but when I print it in the constructor itself then it showing all zeroes.
It is still valid in the constructor so accessing it is not a problem.
So what is the solution.
In general pointers you should avoid pointers (especially when brand new). You need to get some basic concepts down first.
In this case simply replace:
int* visited;
With
std::vector<int> visited;
In the constructor fill this with the appropriate zero values.

C++ Free pointers stored in a vector

So, I have these functions (Game inherits from GameInterface; they both currently have no purpose, I'm just testing whether what I have in mind can be done or not.):
vector<GameInterface*> Game::generateChildren() {
vector<GameInterface*> vgf;
// make 10 copies of this object, increasing the 'npawns' attribute
Game* gi = this;
for (int i = 0; i < 10; ++i) {
gi = new Game(*gi);
vgf.push_back(gi);
++gi->npawns;
}
return vgf;
}
and
const int Library::getBestMovement(GameInterface* gf) const {
vector<GameInterface*> vgf = gf->generateChildren();
int nchildren = vgf.size();
// outputs "child #i has (i+1) pawns" for i in 0..9
for (int i = 0; i < nchildren; ++i) {
cout << "child #" << i << " has " << vgf[i]->num_of_pawns() << " pawns" << endl;
}
// missing some dynamic memory management (deleting the pointers in vgf)
return 0;
}
Since the "children" objects are created with new, and they will no longer be used once getBestMovement ends, I assume I have to free the pointers inside vgf.
The problem is that I've tried everything from
for (auto it = vgf.begin(); it != vgf.end(); ++it)
delete *it;
to using smart pointers, but I always get the same debug assertion error when I execute the program: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse).
Any idea about what the problem is? Thanks
EDIT:
Ok, I had class Game : virtual public GameInterface. Removed the virtual keyword and it works fine now. I don't know why, though (I didn't even know what he virtual keyword did; I'm mostly testing stuff since I'm kind of new to the language, so please bear with me)
EDIT 2:
Forcing the GameInterface destructor to be virtual seems to be the proper solution.
The following code should be vaguely correct:
#include <memory>
#include <vector>
struct GameInterface
{
virtual ~GameInterface() {}
virtual std::vector<std::unique_ptr<GameInterface>> generateChildren() = 0;
};
struct Game : GameInterface
{
std::vector<std::unique_ptr<GameInterface>> generateChildren() override
{
std::vector<std::unique_ptr<GameInterface>> result;
for (int i = 0; i != 10; ++i)
{
result.emplace_back(new Game(result.empty()
? *this
: *result.back()));
++result.back()->npawns;
}
return result;
}
};
int getBestMovement(GameInterface* gf)
{
auto v = gf->generateChildren();
// ...
return 0;
}

How can I do to get correct output in class?

This is the default constructor with no parameters. By default, this allocates space for a
double array of size 10 and assigns a default value of 0 to each of them.
its a ""class"" , I m not sure what i m doing right or wrong..
I fill the public body functions , but my output is nothing suppose to print 0000000000
, I m very new to coding.
class DataVector
{
private:
DataType *m_data;//Pointer to dynamically allocated memory that holds all items
UIntType m_size;//Size of the m_data array
public:
DataVector()
{
double *m_data = new double[m_size];
for (int i = 0; i < m_size; i++)
{
*m_data = 0;
m_data++;
}
}
void PrintItems()
{
for (int i = 0; i < m_size; i++)
{
cout << *m_data << " ";
m_data++;
}
}
};
void TestDataVector()
{
{
DataVector d1;
d1.PrintItems();
}
}
There are a few problems with this implementation of yours:
You are not initializing m_size
You change the value of the pointer m_data which is supposed to hold the address of first member of the array. So, at the end of the initializer, m_data is pointing to a spot one after the block you had allocated by new.
same in the printItems member function, but here the pointer already points to an invalid location.
Also, because you are allocating memory in the constructor, you should also define a destructor to free that memory.

What is wrong with my park_car function?

I'm again doing a task for school and I'm implementing it slowly, I don't know why my park_car function is not working, I just wanted to make a test and the program crashes ... here is my code.
PS: I can't change the ***p2parkboxes because it is given in the starter file like most other variables. I just want to see the first element of Floor 0 as : HH-AB 1234. Your help is most appreciated.
PS2: I can't use the std::string as well it isn't allowed for the task.
#include <iostream>
#include <cstring>
using namespace std;
#define EMPTY "----------"
class Parkbox{
char *license_plate; // car's license plate
public:
Parkbox(char *s = EMPTY); // CTOR
~Parkbox(); // DTOR
char *get_plate(){return license_plate;}
};
class ParkingGarage{
Parkbox ***p2parkboxes;
//int dimensions_of_parkhouse[3]; // better with rows,columns,floors
int rows,columns,floors; // dimensions of park house
int total_num_of_cars_currently_parked;
int next_free_parking_position[3];
// PRIVATE MEMBER FUNCTION
void find_next_free_parking_position();
public:
ParkingGarage(int row, int col, int flr);// CTOR,[rows][columns][floors]
~ParkingGarage(); // DTOR
bool park_car(char*); // park car with license plate
bool fetch_car(char*); // fetch car with license plate
void show(); // show content of garage floor
// by floor
};
Parkbox::Parkbox(char *s ) { // CTOR
license_plate = new char[strlen(s)+1];
strcpy(license_plate, s);
//cout << "ParkBox CTOR" << endl;
}
Parkbox::~Parkbox() { // DTOR
delete [] license_plate;
//cout << "ParkBox DTOR" << endl;
}
ParkingGarage::ParkingGarage(int row, int col, int flr){
rows = row; columns = col; floors = flr;
p2parkboxes = new Parkbox**[row];
for (int i = 0; i < row; ++i) {
p2parkboxes[i] = new Parkbox*[col];
for (int j = 0; j < col; ++j)
p2parkboxes[i][j] = new Parkbox[flr];
}
}
ParkingGarage::~ParkingGarage(){
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j)
delete [] p2parkboxes[i][j];
delete [] p2parkboxes[i];
}
delete [] p2parkboxes;
}
void ParkingGarage::show(){
int i,j,k;
for (i = 0 ; i < floors; i++){
cout << "Floor" << i << endl;
for (j=0;j<rows;j++){
for (k=0;k<columns;k++){
cout << p2parkboxes[j][k][i].get_plate() << " ";
}
cout << endl;
}
}
}
bool ParkingGarage::park_car(char*s){
p2parkboxes[0][0][0] = Parkbox(s); //test
//p2parkboxes[0][0][0] = s; //test
return true;
}
int main(void) {
// a parking garage with 2 rows, 3 columns and 4 floors
ParkingGarage pg1(2, 3, 4);
pg1.park_car("HH-AB 1234");
/*pg1.park_car("HH-CD 5678");
pg1.park_car("HH-EF 1010");
pg1.park_car("HH-GH 1235");
pg1.park_car("HH-IJ 5676");
pg1.park_car("HH-LM 1017");
pg1.park_car("HH-MN 1111"); */
pg1.show();
/*pg1.fetch_car("HH-CD 5678");
pg1.show();
pg1.fetch_car("HH-IJ 5676");
pg1.show();
pg1.park_car("HH-SK 1087");
pg1.show();
pg1.park_car("SE-AB 1000");
pg1.show();
pg1.park_car("PI-XY 9999");
pg1.show(); */
return 0;
}
You did not declare the copy constructor for the Parkbox class. So, the line
p2parboxes[0][0][0] = Parkbox(s)
creates something (instance of Parkbox with a char* pointer) on the stack (and deletes it almost immediately). To correct this you might define the
Parkbox& operator = Parkbox(const Parkbox& other)
{
license_plate = new char[strlen(other.get_plate())+1];
strcpy(license_plate, other.get_plate());
return *this;
}
Let's see the workflow for the
p2parboxes[0][0][0] = Parkbox(s)
line.
First, the constructor is called and an instance of Parkbox is created on stack (we will call this tmp_Parkbox).
Inside this constructor the license_plate is allocated and let's say it points to 0xDEADBEEF location.
The copying happens (this is obvious because this is the thing that is written in code) and the p2parboxes[0][0][0] now contains the exact copy of tmp_Parkbox.
The scope for tmp_Parkbox now ends and the destructor for tmp_Parkbox is called, where the tmp_Parkbox.license_plate (0xDEADBEEF ptr) is deallocated.
p2parboxes[0][0][0] still contains a "valid" instance of Parkbox and the p2parboxes[0][0][0].license_plate is still 0xDEADBEEF which leads to the undefined behaviour, if any allocation occurs before you call the
cout << p2parboxes[0][0][0].license_plate;
Bottom line: there is nothing wrong with the line itself, the problem is hidden within the implementation details of the '=' operator.
At this point it is really better for you to use the std::string for strings and not the razor-sharp, tricky and explicit C-style direct memory management mixed with the implicit C++ copy/construction semantics. The code would also be better if you use the std::vector for dynamic arrays.
The problem here is that you do not have deep copy assignment semantics. When you assign a temporary Parkbox to the Parkbox in the parking garage, the compiler generated assignment operator makes a shallow copy of the pointer license_plate, leaving both Parkboxes pointing at the same memory location. Then the temporary Parkbox goes out of scope and deletes license_plate. Since the other Parkbox is pointing at the same spot its license_plate gets deleted, too.
There are a couple solutions. One way to solve the problem is to define an assignment operator and a copy constructor that provide proper semantics, i.e. that perform deep copies of the license plate string. The better option, and the one that makes better use of C++, is to use std::strings instead of manually allocated C-strings. I strongly suggest the second approach, though working through the first might be instructive.
From the OP:
I solved the Problem with :
void Parkbox::change_plate(char *s){
delete [] license_plate;
license_plate = new char[strlen(s)+1];
strcpy(license_plate, s);
}

Deallocation of an array of objects?

I'm having some issues deallocating arrays of a class I have. Below is the Class, a simplified implementation and my code I have tried to use to close it.
Characters class
#include <cstdlib>
class Character
{
private:
bool human;
int Xposition; // the character's postion on the board.
int Yposition; // the character's postion on the board.
bool alive;
public:
Character(); //This is my constructor
~Character(); //This is my destructor
bool isHuman(); //return whether type 1 aka Human
bool isZombie(); //return whether type 2 aka Zombie
void setHuman(); //set to type 1 or Human
void setZombie(); //set to type 2 or Zombie
void setPos(int xpos, int ypos); //set the board position
int X();
int Y();
bool isAlive(); //checks to see if a Human is still alive and to be displayed
bool Dead(); //kills the character and sets alive to false
int num_moves_allowed; //number of moves allowed.
};
Allocation code:
Character *characters[11];
int human_count = 0;
for(int i=0; i<12; i++)
{
characters[human_count] = new Character();
human_count++;
}
Termination code:
for(i=11;i<=0;i--)
{
if(characters)
{
characters[i]->~Character();
delete characters[i]; characters[i] = NULL;
}
}
if(characters)
{
//ERROR IS HERE
delete [] characters;
}
I have tried a number of different "delete" commands on the array and I keep getting an "Debug Assertion Failed!" window. It says that the dbgdel.cpp from visual studio vctools is the problem place on Line 52.
It also says "Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
Someone please help me I'm sure this is very simple.
I'd suggest you avoid using arrays all together. Use a vector of characters.
Declare your vector as
vector<Character> vCharacters;
then insert objects as
for(int i = 0; i < 100; i++)
vCharacters.push_back(Character());
If you want to store pointers to Character objects then wrap them in a shared_ptr which will take care of deallocating them for you.
vector<shared_ptr<Character>> vCharacters;
for(int i =0; i < 100; i++)
{
shared_ptr<Character> spCharacter(new Character());
vCharacters.push_back(spCharacter);
}
Avoid managing memory yourself when C++ can do it fo ryou
The characters array was allocated on the stack, so you don't have to delete it. However, if you want the array to survive the local scope, create it with something like this:
Character **characters = new Character[11];
then your delete[] line should work fine.
Also note that you don't need to call the destructor of Character explicitly: it is called automatically by delete.
As obelix mentioned, you should use a vector from the Standard Template Library.
However, if you're determined to use a raw array:
const int MAX_CHARACTERS = 11;
Character *characters[MAX_CHARACTERS];
for(int characterCount = 0; characterCount < MAX_CHARACTERS; ++characterCount)
{
characters[characterCount] = new Character();
}
...
if (characters != NULL)
{
for(int i = 0; i < MAX_CHARACTERS; ++i)
{
delete characters[i];
}
}
Paolo Capriotti is correct that characters should be declared with new if you want it to last beyond its scope:
const int MAX_CHARACTERS = 11;
Character **characters = new Character*[MAX_CHARACTERS];
for(int characterCount = 0; characterCount < MAX_CHARACTERS; ++characterCount)
{
characters[characterCount] = new Character();
}
...
if (characters != NULL)
{
for(int i = 0; i < MAX_CHARACTERS; ++i)
{
delete characters[i];
}
delete [] characters;
}
A better solution is the standard vector class:
#include <vector>
...
const int MAX_CHARACTERS = 11;
std::vector<Character> characters;
for (int i = 0; i < MAX_CHARACTERS; ++i)
{
characters.push_back(Character());
}
...
characters.clear();
Notice how much easier the cleanup was? (And in this case, it's optional, since when characters is destroyed it will automatically call the destructor of each item it contains.)
Also:
Character *characters[11];
should be
Character *characters[12];
and
for(i=11;i<=0;i--)
should be
for(i=11;i>=0;i--)
i realize this is a simplified use and all, but why bother with heap access at all?
just using
Character characters[11];
could be just as valid, and safe.
std::vector<> is nice, but if the list is always fixed size, and there's no heap involved in member data, why not?