I'm trying to make a data structure which contains all the monsters in the game. For some reason when I allocate new monster i get "cannot convert Monster** to p_monster {Aka monster*} in initialization. If you could help me out it would be much appreciated. Thanks in advance
struct Monster {
int x;
int y;
int health;
Monster *next;
};
typedef Monster* p_monster;
class gameUtils {
protected:
p_monster monster};
public:
gameUtils(){
monster=NULL;
...}
function(){
monster = getMonster(monster)} // so that I can assign whatever value I want to monster->last->next through the function itself
p_monster getMonster(p_monster monster){
p_monster newMonster = new p_monster;
if(monster==NULL){
monster=newMonster;
}else{
.... // find last monster then create new one and pass it to caller
return monster; // returns new monster without any value
}
Type aliases are slightly more clear with using.
//typedef Monster* p_monster;
using p_monster = Monster*;
p_monster is Monster*. Now when you call new T then an object of type T is created and as a result you get a pointer to that object, a T*.
When you write:
p_monster newMonster = new p_monster;
Then new dynamically allocates a p_monster, a Monster*, and you get a p_monster*, a Monster**. There is no conversion from Monster** to Monster*, hence the error.
I suggest a std::vector<Monster> to store your monsters. Your approach for the list is intrusive, a Monster in your design is aware of being in a linked list, it has a next member. When you use a std::vector<Monster> you can store Monsters in a vector, outside of the vector, or in a different container, the Monster needs not care.
Also not using manual memory managment via raw pointers will make your code much simpler.
struct Monster {
int x;
int y;
int health;
Monster(int x,int y,int health) : x(x),y(y),health(health) {}
};
struct gameUtils {
std::vector<Monster> monster;
Monster& createMonster(int x,int y,int health) {
monster.emplace_back(x,y,health);
return monster.back();
}
};
A linked list in C++ is std::list, though a vector profits a lot from its elements being stored in contiguous memory. It profits from that so much, that it is often superior to a std::list even though time complexity of some methods suggests otherwise.
Related
I build two classes, cell, and HashTable, I want to declare an array of cells as a hashTable class member.
I want to do it with primitive vars like int,chars, like I declare array of cars as a hashTable class member.
I tried to declare an array of cells in some ways :
1.
class HashTable{
public:
int size;
int numOfKeys;
Cell* table = new Cell[10];
int cars[4];
//static void resize(HashTable &ht);
static void reinsert(Cell* new_table, int new_size, Node<Player*> *data);
HashTable() : size(10), numOfKeys(0) {
table = new Cell[10];
}
2. class HashTable{
public:
int size;
int numOfKeys;
Cell* table = new Cell[10];
int cars[4];
//static void resize(HashTable &ht);
static void reinsert(Cell* new_table, int new_size, Node<Player*> *data);
HashTable() : size(10), numOfKeys(0),table(new Cell[10]) {
}
I try to declare it in the constructor but it doesn't work.
How am I supposed to define this array?
Thanks !
I don't see any error , but I can see the array of cars but not the array of table
class Cell
{
public:
AVLTree<Player*>* AllPlayers;
int treeSize;
Cell() : treeSize(0) {
AllPlayers = new AVLTree<Player*>();
}
~Cell(){
delete AllPlayers;
};
Cell(const Cell &sec) = default;
Cell &operator=(const Cell &sec) = default;
void reinsert(Player* pl)
{
treeSize++;
AllPlayers->root = AllPlayers->insert(AllPlayers->root, pl,NULL);
}
int insert(Player* pl)
{
if (!(AllPlayers->findNode(AllPlayers->root,pl)))
{
AllPlayers->root = AllPlayers->insert(AllPlayers->root,pl,NULL);
treeSize++;
return 0;
}
return -1;
}
int remove(Player* pl)
{
AllPlayers->root = AllPlayers->remove(AllPlayers->root,pl);
treeSize--;
return treeSize;
}
};
class HashTable{
public:
int size;
int numOfKeys;
Cell* table;
int cars[4];
//static void resize(HashTable &ht);
static void reinsert(Cell* new_table, int new_size, Node<Player*> *data);
HashTable() : size(10), numOfKeys(0) {
table = new Cell[10];
}
~HashTable() { delete[] table; }
Fear not! You have an array of ten Cells pointed at by table.
table is a pointer. It holds an address, nothing more. A pointer knows only where an object is (note that the object may have been subsequently destroyed, a pointer has no way of knowing, or the pointer may not have been initialized). If the object referenced to by the pointer is an array, the pointer has no way to know how many items are in the array. The IDE cannot show that there are ten items in the array pointed at by table because all it knows is the pointer and the pointer does not know. If you want the IDE to display what is in those ten Cells, you need to set up what are commonly called "watch expressions" for each subobject in the array or play games with casting to tell the watch expression how to interpret the object at the pointer.
cars is an array. Arrays represent the whole whole array. They know their size, their dimensions and all of the data in the array. The IDE can show you all of the items in the cars array because cars knows all that there is to know.
If you know you will always and forever have 10 Cells, get rid of the pointer and define an array. If you don't know the size, you'll have to live with what the IDE can show you.
Side note: Some IDEs are smart enough to interpret a std::vector and can display the objects in the std::vector. Consider using std::vector instead of a dynamic array where possible. Intelligent handing in IDEs is but a small benefit of std::vector.
Side note: When I say object, I mean it in the C++ definition of object, not in the OOP sense of an instance of a class.
I am practicing some C++ and I was confused about why I need double pointers for an array of objects(such as a node struct). Here is a simple code snippet to explain my situation:
struct HashNode{
HashNode* next;
int data;
int key;
int hashCode;
HashNode::HashNode(
HashNode* next,
const int& data,
const int& key,
const int& hashCode
) : next(next), data(data), key(key), hashCode(hashCode)
{}
};
class HashMap{
public:
HashMap();
HashMap(int tableSize);
~HashMap();
private:
//Here is the double pointer
HashNode** table;
};
HashMap::HashMap(){
//Here is the array initialization
table = new HashNode*[100];
}
I have removed the code that is unnecessary for the question.
If I remove the double pointer as such:
HashNode* table;
and
table = new HashNode[100];
I get the following error.
hashmap.cpp: In method `HashMap::HashMap()':
hashmap.cpp:87: no matching function for call to `HashNode::HashNode ()'
hashmap.cpp:61: candidates are: HashNode::HashNode(const HashNode &)
hashmap.cpp:58: HashNode::HashNode(HashNode *, const int &, cons
t int &, const int &)
which shows me that the HashNode tries to run a constructor.
If I change only the initialization of the array as table = new HashNode*[100]; while keeping HashNode* table; then I get the following error.
hashmap.cpp: In method `HashMap::HashMap()':
hashmap.cpp:87: assignment to `HashNode *' from `HashNode **'
My assumption is that when I make an array of objects, I need the lifetime of the objects to be for the duration of the program as well. This requires me to use pointers for the objects as well as the array. Therefore, I need to have double pointers for the array since it points to pointers and I need pointers for the objects.
However, I am still unsure and I cannot really find any good explanations online. Could someone please explain this situation?
This implementation uses separate chaining with linked lists for managing hash collisions. Therefore, table is an array of pointers to HashNode, meaning that it needs two asterisks:
One asterisk comes from the type of array element, which is HashNode*
The other asterisk comes from making an array of HashNode*
That is also why you have an asterisk in the new expression:
table = new HashNode*[100];
// ^
It seems you are very new to c++ pointers.
What you are currently doing is make array of 100 pointers. So Compiler is not giving you any error because actual objects are not created with this line.
HashNode **table = new HashNode*[100];
But when you use
HashNode *table = new HashNode[100];
Then you are trying to create 100 objects for HashNode;
But you do not have default constructor so compiler giving you the above error.
I have attached following working code. check it out.
#include <iostream>
using namespace std;
struct HashNode{
HashNode* next;
int data;
int key;
int hashCode;
HashNode(){}
HashNode(
HashNode* next,
const int& data,
const int& key,
const int& hashCode
) : next(next), data(data), key(key), hashCode(hashCode)
{}
};
class HashMap{
public:
HashMap();
private:
//Here is the double pointer
HashNode* table;
};
HashMap::HashMap(){
//Here is the array initialization
table = new HashNode[100];
}
int main() {
// your code goes here
HashMap ob;
std::cout << "him" << std::endl;
return 0;
}
Here you are declaring array of pointers
HashNode** table;
That is an array named table with pointers of the type hashNode.
I saw a few examples of creating a vector of class objects and many of them uses a pointer and new keyword. However, in many cases the delete is not used to free up memory allocated by new. I would like to know if the following piece of code uses delete properly.
I have a class Marker:
class Marker{
public:
Marker(int, float, float);
int marker_id();
private:
int id;
float mx;
float my;
};
It's constructor is:
Marker::Marker(int idno, float x, float y){
//ctor
id = idno;
mx = x;
my = y;
}
I need a vector marker_vec with objects or instances of Marker class. Hence, I wrote the following piece of code:
vector <Marker> marker_vec;
Marker *m = new Marker(last_id, m_x, m_y);
marker_vec.push_back(*m);
delete m;
If I use the above code in a loop to create marker_vec[0] and marker_vec[1], I believe that the delete wouldn't delete them and will only free up the pointer m. Is there any disadvantages for the above method?
This piece of code is alright, since when you push_back, the contents referenced by the m pointer will be copied and added as the last element of the vector. You're doing good by deallocating the memory you set properly (for every new there is a corresponding delete).
vector <Marker> marker_vec;
Marker *m = new Marker(last_id, m_x, m_y);
marker_vec.push_back(*m);
delete m;
I just think it's unnecessary for you to use pointers in this case having one type of Marker class and your std::vector of type <Marker>.
I would personally improve the implementation of this code to being statically instantiated. It's simple and cleaner in this case:
vector <Marker> marker_vec;
Marker m(last_id, m_x, m_y);
marker_vec.push_back*m);
However, if you maybe had inheritance like different type of markers:
class HighlighterMarker : public Marker { };
and
class PenMarker: public Marker { };
Only then, it'd make sense for you to use dynamic memory and your vector to be declared as:
std::vector <Marker*> marker_vec. This one can store all your references to any type of derived class Marker,
I have a class symbol_table that has a vector of objects of another class row_st.also I have an enter method where inserts objects of row_st with a passed name into the vector of desired symbol_table.but when I call the enter to enter objects with name :
a;b;c;Iwill get the following result: a,b,c;b,c;c.the first element of vector gets the name of all the entered objects. and the second element also gets the name of the later entries.
class row_st
{
public:
char* name;
type_u type;//int:0,flaot:1;char:2,bool:3,array:
int offset;
symbol_table *next;
symbol_table *current;
};
class symbol_table
{
public:
vector <row_st *> row;
int type;
int header;
int starting_stmt;
int index;
int i;
symbol_table *previous;
symbol_table(){ header=0;
previous=0; index=0;i=0;starting_stmt=0;}
};
and here it is the enter method:
int enter(symbol_table *table,char* name,type_u type){
row_st *t=new row_st;
t->name=name;
t->type=type;
t->offset=table->index;
t->current=table;
table->index++;
t->next=0;
table->row.push_back(t);
table->header +=1;
return table->row.size()-1;
}
the push_backed elements all points to the same address.the new call makes the same row_st every time it is called.what should I do?
You can't use character pointers like that - you need to allocate storage to them. But as you are using C++, you should remove them and replace them with instances of the std::string class, which will manage storage for you.
As Neil Butterworth's answer suggest, the trouble is probably not with this code, but the place where you call it. Using character pointers does not make it impossible to make things work, just harder.
The problem in this case is definitely not with push_back. If you posted the method where you call this code it might be possible to see exactly what goes wrong.
I am relatively new to C++ programming, but am a C programmer of 10 years so am more comfortable with pointers to objects than I am with references to objects.
I'm writing a Solitaire game - is this design unsafe? Is there a better way?
Anyway, I have a class SolitaireGame:
class SolitaireGame:
{
public:
SolitaireGame( int numsuits = 1 );
private:
Deck * _deck;
vector<Card> _shoe;
};
The Deck is defined thus:
class Deck:
{
public:
Deck::Deck( vector<Card>& shoe );
~Deck();
int DealsLeft() const { return deals_left; }
Card * PullCard();
private:
int deals_left;
int num_each_deal;
deque<Card *> _cards;
};
The Deck constructor, takes a reference to a vector of Card objects ( the shoe, normally 104 cards ) and pushes a pointer to each card onto it's own deque of pointers.
Deck::Deck( vector<Card>& shoe )
{
vector<Card>::iterator iter = shoe.begin();
while( iter != shoe.end() )
{
_cards.push_front( &(*iter) );
iter++;
}
}
}
The shoe is created in the SolitaireGame constructor. Once this vector of dynamically created Card objects has been created - I then pass a reference to this vector to the constructor.
SolitaireGame::SolitaireGame( int numsuits ):_numsuits(numsuits )
{
Card * c;
vector<Card> _shoe;
for( int i = 0; i < NUM_CARDS_IN_SHOE; i++ )
{
c = new Card();
_shoe.push_back( *c );
}
_deck = new Deck( _shoe );
}
My idea was that the shoe would be the container for the actual memory for the Card objects and the Deck and Columns just handle pointers to those Card objects.
Just taking this snippet of code, you leak dynamically created cards.
Card * c;
vector<Card> _shoe;
for( int i = 0; i < NUM_CARDS_IN_SHOE; i++ )
{
c = new Card();
_shoe.push_back( *c );
}
_shoe.push_back( *c ) adds a copy of the Card object pointed to by c to the vector of Cards. You then fail to delete the original Card as created in the line before.
Allocating a vector of NUM_CARDS_IN_SHOE Cards can much more simply be achieved like this:
std::vector<Card> _shoe( NUM_CARDS_IN_SHOE );
Looking at your card structure, it looks like you have (or nearly have) strict ownership between objects so I don't think that you need to dynamically create your Cards.
Note that your local variable _shoe is shadowing the class variable _shoe. This probably isn't what you want as the local _shoe which you pass to the Deck constructor will go out of scope at the end of the constructor.
If you reorder you variables in SolitaireGame, you can probably do something like this:
class SolitaireGame:
{
public:
SolitaireGame( int numsuits = 1 );
private:
vector<Card> _shoe;
Deck _deck;
};
SolitaireGame::SolitaireGame( int numsuits )
: _shoe(NUM_CARDS_IN_SHOE)
, _deck(_shoe)
{
}
I've changed _deck from being a pointer. I'm using the fact that member variables are constructed in the order declared in the class definition, so _shoe will be fully constructed before it is passed as a reference to the constructor for _deck. The advantage of this is that I have eliminated the need to dynamically allocate _deck. With no uses of new, I know that I can't have any missed calls to delete as nothing needs to be deallocated explicitly.
You are right that you can store pointers to the Cards in _shoe in your _deck without any memory management issues, but note that you must not add or remove any of the Cards in the _shoe during the lifetime of the game otherwise you will invalidate all of the pointers in _deck.
I think there're two mistakes:
When you do _shoe.push_back( *c );, you're creating a copy of the Card object, so the memory reserved to c will never be freed. Btw, you should always check that for each new exists a complementary delete. Where is your delete?
In your Deck constructor you're saving pointers to objects that reside in the stack (vector<Card> _shoe;), so as soon as the SolitaireGame constructor ends, they will be deleted and your pointers will be invalid. EDIT: I see you've got another _shoe in your class, so it's not necessary to declare another _shoe local variable, in fact just by not declaring it you will solve this issue.
I hope this helps you a bit.
Initial thoughts:
In class SolitaireGame, you declare _shoe as:
vector<Card> _shoe;
but in the constructor you push heap objects on to it like this:
c = new Card();
_shoe.push_back( *c );
So, you need to declare it like this:
vector<Card*> _shoe;
You don't initialise variables in constructors, such as deals_left and num_each_deal in class Deck. I'll assume you left it out to not clutter up the code, but it's a good idea.
Class SolitaireGame creates and owns the Deck objects. It also has a Deck with pointers to SolitaireGame's Card objects. The ownership here is unclear - who deleted them? While having pointers to objects in multiple containers will work, it can make debugging more difficult, as there's scope for multiple deletion, using after it's been deleted, leaks etc. Perhaps the design could be simplified. Perhaps have Deck own the Card objects initially, and when they're removed, they get put into the vector in SolitaireGame, and don't exist in both at the same time.
In the constructor for SolitaireGame, you declare another vector of cards, which shadows the one declare in the class declaration. When you push the Card objects onto it, they'll not get pushed to the correct vector, which will go out of scope at the end of the constructor, and your class member will be empty. Just get rid of it from the constructor.
Anyway, I need a cup of tea. After that I'll take another look and see if I can suggest anything else.
I don't think the new keyword should appear anywhere in the code of these classes, and I don't see why you'd go through the trouble to share cards through pointers. Storing addresses of items held in a vector is recipe for disaster - you need to guarantee that there will be no modifications to the vector after you take the addresses, as it tends to move things around in memory without telling you.
Assuming a Card object doesn't store anything besides one or two ints, it would be a lot simpler to work with copies and values.
_deck = new Deck( _shoe );
Again, I don't see a slightest reason to increase complexity of the program by allocating an object containing two ints and a deque dynamically.
If you are worried about cost of copying some of the larger classes you have (which I would estimate has zero impact on perceived performance here), then simply don't copy them, and pass them around by const reference (if you don't need to mutate the instance), or non-const reference/pointer otherwise.
This program will leak memory , Want to find out why ? or how ?
push_back
Do remember this call do not insert your supplied element , But creates a copy of it for own use. Read this for detail
So
Card *c = new Card(); // This is on heap , Need explicit release by user
If you change it to
Card c; // This is on stack, will be release with stack unwinding
Copy below program and execute it, {I simply added logging}, try with both option, above
#include<iostream>
#include <vector>
#include <deque>
using namespace std;
const int NUM_CARDS_IN_SHOE=120;
class Card
{
public:
Card()
{
++ctr;
cout<<"C'tor callend: "<<ctr<<" , time"<<endl;
}
~Card()
{
++dtr;
cout<<"D'tor called"<<dtr<<" , time, num still to release: "<<((ctr+cpy)-dtr)<<endl;
}
Card& operator=(const Card & rObj)
{
return *this;
}
Card (const Card& rObj)
{
++cpy;
cout<<"Cpy'tor called"<<cpy<<endl;
}
private:
static int ctr,dtr,rest,cpy;
};
int Card::ctr;
int Card::dtr;
int Card::rest;
int Card::cpy;
class Deck
{
public:
Deck::Deck( vector<Card>& shoe );
~Deck();
int DealsLeft() const { return deals_left; }
Card * PullCard();
private:
int deals_left;
int num_each_deal;
std::deque<Card *> _cards;
};
Deck::Deck( vector<Card>& shoe )
{
vector<Card>::iterator iter = shoe.begin();
while( iter != shoe.end() )
{
_cards.push_front( &(*iter) );
iter++;
}
}
class SolitaireGame
{
public:
SolitaireGame( int numsuits = 1 );
private:
Deck * _deck;
std::vector<Card> _shoe;
};
SolitaireGame::SolitaireGame( int numsuits )
{
Card * c;
vector<Card> _shoe;
for( int i = 0; i < numsuits; i++ )
{
c = new Card();
_shoe.push_back( *c );
}
_deck = new Deck( _shoe );
}
int main()
{
{
SolitaireGame obj(10);
}
int a;
cin>>a;
return 0;
}
Since such a game object always has its own deck you should consider making the Deck object a real member inside SolitairGame -- not just a pointer. This will make life-time management of the deck object much simpler. For example, you won't need a custom destructor anymore. Keep in mind that STL containers contain copies. If you write something like
myvector.push_back(*(new foo));
you have a memory leak.
In addition, storing pointers to elements of a vector is dangerous because the pointers (or iterators in general) might become invalid. For a vector this is the case when it needs to grow. An alternative is std::list which keeps iterators valid after insertion, deletion, etc.
Also, keep in mind that in C++ structs and classes usually get implicit copy constructors and assignment operators. Honor the rule of three. Either disallow copying and assignment or make sure that resources (including dynamically allocated memory) is properly managed.