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.
Related
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.
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 have a class that contains several arrays whose sizes can be determined by parameters to its constructor. My problem is that instances of this class have sizes that can't be determined at compile time, and I don't know how to tell a new method at run time how big I need my object to be. Each object will be of a fixed size, but different instances may be different sizes.
There are several ways around the problem:- use a factory- use a placement constructor- allocate arrays in the constructor and store pointers to them in my object.
I am adapting some legacy code from an old application written in C. In the original code, the program figures out how much memory will be needed for the entire object, calls malloc() for that amount, and proceeds to initialize the various fields.
For the C++ version, I'd like to be able to make a (fairly) normal constructor for my object. It will be a descendant of a parent class, and some of the code will be depending on polymorphism to call the right method. Other classes descended from the same parent have sizes known at compile time, and thus present no problem.
I'd like to avoid some of the special considerations necessary when using placement new, and I'd like to be able to delete the objects in a normal way.
I'd like to avoid carrying pointers within the body of my object, partially to avoid ownership problems associated with copying the object, and partially because I would like to re-use as much of the existing C code as possible. If ownership were the only issue, I could probably just use shared pointers and not worry.
Here's a very trimmed-down version of the C code that creates the objects:
typedef struct
{
int controls;
int coords;
} myobject;
myobject* create_obj(int controls, int coords)
{
size_t size = sizeof(myobject) + (controls + coords*2) * sizeof(double);
char* mem = malloc(size);
myobject* p = (myobject *) mem;
p->controls = controls;
p->coords = coords;
return p;
}
The arrays within the object maintain a fixed size of the life of the object. In the code above, memory following the structure of myobject will be used to hold the array elements.
I feel like I may be missing something obvious. Is there some way that I don't know about to write a (fairly) normal constructor in C++ but be able to tell it how much memory the object will require at run time, without resorting to a "placement new" scenario?
How about a pragmatic approach: keep the structure as is (if compatibility with C is important) and wrap it into a c++ class?
typedef struct
{
int controls;
int coords;
} myobject;
myobject* create_obj(int controls, int coords);
void dispose_obj(myobject* obj);
class MyObject
{
public:
MyObject(int controls, int coords) {_data = create_obj(controls, coords);}
~MyObject() {dispose_obj(_data);}
const myobject* data() const
{
return _data;
}
myobject* data()
{
return _data;
}
int controls() const {return _data->controls;}
int coords() const {return _data->coords;}
double* array() { return (double*)(_data+1); }
private:
myobject* _data;
}
While I understand the desire to limit the changes to the existing C code, it would be better to do it correctly now rather than fight with bugs in the future. I suggest the following structure and changes to your code to deal with it (which I suspect would mostly be pulling out code that calculates offsets).
struct spots
{
double x;
double y;
};
struct myobject
{
std::vector<double> m_controls;
std::vector<spots> m_coordinates;
myobject( int controls, int coordinates ) :
m_controls( controls ),
m_coordinates( coordinates )
{ }
};
To maintain the semantics of the original code, where the struct and array are in a single contigious block of memory, you can simply replace malloc(size) with new char[size] instead:
myobject* create_obj(int controls, int coords)
{
size_t size = sizeof(myobject) + (controls + coords*2) * sizeof(double);
char* mem = new char[size];
myobject* p = new(mem) myobject;
p->controls = controls;
p->coords = coords;
return p;
}
You will have to use a type-cast when freeing the memory with delete[], though:
myobject *p = create_obj(...);
...
p->~myobject();
delete[] (char*) p;
In this case, I would suggest wrapping that logic in another function:
void free_obj(myobject *p)
{
p->~myobject();
delete[] (char*) p;
}
myobject *p = create_obj(...);
...
free_obj(p);
That being said, if you are allowed to, it would be better to re-write the code to follow C++ semantics instead, eg:
struct myobject
{
int controls;
int coords;
std::vector<double> values;
myobject(int acontrols, int acoords) :
controls(acontrols),
coords(acoords),
values(acontrols + acoords*2)
{
}
};
And then you can do this:
std::unique_ptr<myobject> p = std::make_unique<myobject>(...); // C++14
...
std::unique_ptr<myobject> p(new myobject(...)); // C++11
...
std::auto_ptr<myobject> p(new myobject(...)); // pre C++11
...
New Answer (given comment from OP):
Allocate a std::vector<byte> of the correct size. The array allocated to back the vector will be contiguous memory. This vector size can be calculated and the vector will manage your memory correctly. You will still need to be very careful about how you manage your access to that byte array obviously, but you can use iterators and the like at least (if you want).
By the way here is a little template thing I use to move along byte blobs with a little more grace (note this has aliasing issues as pointed out by Sergey in the comments below, I'm leaving it here because it seems to be a good example of what not to do... :-) ) :
template<typename T>
T readFromBuf(byte*& ptr) {
T * const p = reinterpret_cast<T*>(ptr);
ptr += sizeof(T);
return *p;
}
Old Answer:
As the comments suggest, you can easily use a std::vector to do what you want. Also I would like to make another suggestion.
size_t size = sizeof(myobject) + (controls + coords*2) * sizeof(double);
The above line of code suggests to me that you have some "hidden structure" in your code. Your myobject struct has two int values from which you are calculating the size of what you actually need. What you actually need is this:
struct ControlCoord {
double control;
std::pair<double, double> coordinate;
};
std::vector<ControlCoord>> controlCoords;
When the comments finally scheded some light on the actual requirements, the solution would be following:
allocate a buffer large enough to hold your object and the array
use placement new in the beginning of the buffer
Here is how:
class myobject {
myobject(int controls, int coords) : controls(controls), coords(coords) {}
~myobject() {};
public:
const int controls;
const int coords;
static myobject* create(int controls, int coords) {
std::unique_ptr<char> buffer = new char[sizeof(myobject) + (controls + coords*2) * sizeof(double)];
myobject obj* = new (buffer.get()) myobject(controls, coords);
buffer.release();
return obj;
}
void dispose() {
~myobject();
char* p = (char*)this;
delete[] p;
}
};
myobject *p = myobject::create(...);
...
p->dispose();
(or suitably wrapped inside deleter for smart pointer)
I am trying to implement a stack using an array. This is what I have in my
header file.I plan to assign the value to maxsize in the constructor. However, i keep getting errors. How can i fix this?
class stack {
private:
const int maxsize;
int arrays[maxsize];
int top;
public:
stack();
void additem(int);
void print();
};
A good fix would be:
class stack
{
std::vector<int> arrays;
int top;
public:
stack(int maxsize) : arrays(maxsize), top(0) {}
};
This way, you do not have any possibility of memory management bugs; your class behaves properly when copied, moved, swapped, etc. and your code is very simple.
An alternative, with a minimal memory footprint would be:
class stack
{
std::unique_ptr<int[]> arrays;
int maxsize;
int top;
public:
stack(int maxsize) : arrays(new int[maxsize]), maxsize(maxsize), top(0) {}
};
This version is movable, but will give compile errors when copied (as opposed to some of the other suggestions to use raw pointer, which will compile successfully and then give memory corruption at runtime). To make this class copyable you'd need to write your own copy-constructor and copy-assignment operator.
C++ doesn't allow variable-length arrays. Instead of an array, you can use a pointer and dynamic allocation.
And to initialize a const member, you have to do it in the initializer list of the constructor.
class stack {
private:
const int maxsize;
int *arrays;
int top;
public:
stack(int max = 10) : maxsize(max) {
arrays = new int[max];
top = 0;
}
void additem(int);
void print();
};
See How to initialize a const field in constructor?
You'll also then need a destructor that does delete[] arrays;.
But rather than using a C-style array, you'd probably find it easier to use std::vector<int>. This doesn't require specifying a maximum length in the first place, it will expand as needed.
Of course, you could skip this whole exersize and use std::stack<int>.
If you want maxsize to always be 10, you could do something like this:
class stack {
private:
static const int maxsize = 10;
int arrays[maxsize];
...
Note that I've made maxsize static. It will be the same for all instances of stack and is defined at compile time. Thus you can use it as an array size.
If you want maxsize to be variable, then you'll need to use dynamic allocation:
class stack {
private:
const int maxsize;
int* arrays;
...
public:
stack(int maxsize) : maxsize(maxsize), arrays(0) {
arrays = new int[maxsize];
}
~stack() { delete[] arrays; }
...
Note here that you must delete the memory you dynamically allocate. The usual place to do that is the destructor. If you want to go this route, you could also just use a std::vector<int> and get rid of maxsize entirely. That frees you from having to do any manual memory management.
In C++, I'm having trouble with pointers etc. How can I fix the following problem?
error: no match for 'operator=' in '(stage->Stage::tiles + ((unsigned int)(((unsigned int)t) * 12u))) = (operator new(12u), (, ((Tile*))))'|
note: candidates are: Tile& Tile::operator=(const Tile&)|*
stage.h
#include "Tile.h"
class Stage {
public:
Tile *tiles;
int size;
void init(int size);
};
stage.cpp
void Stage::init(int size) {
this->size = size;
this->tiles = new Tile[size];
}
application.cpp
#include "Stage.h"
#include "Tile.h"
bool setTiles( Stage * stage ) {
for( int t = 0; t < stage->size; t++ ) {
stage->tiles[t] = new Tile();
}
return true;
}
stage.init(1234);
setTiles( &stage );
Also, I don't really know when to use object.attribute and when to use object->attribute?
stage->tiles[t] = new Tile();
You're calling new on something that's not a pointer. True, tiles is a pointer to an array, however, each element of that array is NOT a pointer. In order for that work, you would need an array of pointers, or a pointer to a pointer ,such as:
Tile **tiles;
What you could also do is create a separate pointer object, allocate it, and then copy the data to your array element by using
stage->tiles[i] = *somePointer;
and then deleting the pointer afterwards to free that allocated memory. This will preserve the copy because you invoked the copy constructor.
You are trying to allocate a pointer with a pointer to an array. Try this one:
class Stage {
public:
Tile **tiles;
void init(int size);
};
stage->tiles[t] = new Tile();
The above is not a valid C++ code, which you are perhaps confusing with the way new is used in other language such as C#. Though new can be used to allocate dynamic memories, but assigning an object to a particular element in the dynamically created array doesn't need the new construct. In fact, the object is already created as soon as you called new Tile[size]. What you may want to do is, create an object of type Tile and assign it to a particular element in tiles.
Tile myTile;
// do something with myTile
this->tiles[0] = myTile;
new Tiles() returns a pointer to a Tiles instance.
Tile *tiles defines an array out Tiles, not pointers.
Start with Tile **tiles instead.