I have an array of pointers to a structure called "table" (the structure is called Node).
I declare the array as so in the class:
Node * table;
Then, in another method, I initalize the table:
this->table = new Node [this->length];
And everything works fine. this->length is a valid entry, this->table is pointing to the right array, and etc. However, then I try to change the value of the elements:
for(int i = 0; i < this->length; i++) {
this->table[i] = new Node;
}
Or even
for(int i = 0; i < this->length; i++) {
this->table[i] = 0;
}
And everything starts bugging out. Why can't I set these pointers to anything?
This is the error I get:
(Where line 15 is the line of "this->table[i] = new Node;").
I hate to post long segments of code, so here's a shortened version of the code itself:
template <class T, class S>
class HashMap {
public:
HashMap();
private:
struct Node;
Node * table;
static const unsigned length = 100;
};
template <class T, class S>
HashMap<T, S>::HashMap() {
this->table = new Node [HashMap::length];
for(int i = 0; i < HashMap::length; i++) {
this->table[i] = new Node;
}
}
template <class T, class S>
struct HashMap<T, S>::Node {
T value;
S key;
Node * next;
};
No research I'm doing is telling me what the error is; any help is appreciated!
You don't have an array of pointers. You have an array of Nodes. Apparently, what you want is something like this:
Node ** table;
...
this->table = new Node*[this->length];
Or maybe you don't actually need an array of pointers, but simply an array of nodes. In that case, no extra initialization is needed beyond:
this->table = new Node[this->length];
Beyond that, unless this is a learning exercise, take a look at the standard library, which has dynamic arrays and hash maps all ready for you.
table is not an array of pointers. It's an array of Nodes (or rather, it points to an array of Nodes). The type of table is Node*; the type of table[i] is Node, not Node*.
If you actually do want an array of pointers, then you need
Node** table;
table = new Node*[length];
Or better still, something like
vector<unique_ptr<Node>> table;
table.resize(length);
You do not have declared an array of pointers.
Node *table(point to a node)
Node **table(point to an array Nodes)
Node** table;
table =new Node*[this->length];
for(int i=0;i<this->length;i++)
{
table[i]=new Node;
}
this->table = new Node [HashMap::length];
this->table is of type Node* and new Node [HashMap::length] also returns a Node* , i.e. an array of Node of lenght HashMap::length is created and the array address is stored in this->table pointer.
this->table[i] = new Node;
As an example, we can define:
int* arr = new int[10];
Here arr is of type int* but arr[0] will be of type int.
similarly, this->table[i] is of type Node and new Node returns Node*. Hence incompatible types. Correct line would be
this->table[i] = *new Node;
But, this line is unnecessary as the array of Nodes is already created and the memory is allocated. Using this line in the code will lead to a memory leak.
Related
I am confused between
vector<node>* children = new vector<node>;
vector<node> *children = new vector<node>;
vector<node*> children = new vector<node>;
I just want to implement a general tree data structure as
struct node{
int index;
vector<int> sol;
vector<node *> children;
};
node *createNode(int indexVal)
{
node* n = new Node();
n->index = indexVal;
vector<int>* soll = new vector<int>;
n->sol = soll;
vector<node>* childrenn = new vector<node *>;
n->children = childrenn;
return n;
}
void addChildren(node* curr, node* child)
{
//something like
curr->push_back(child);
};
I want to be able to modify sol and children vector in which ever scope I want, given that I have a node pointer
I am confused which one of the three given will be the best results, how will they differ?
Also how would this extend to 2-d vectors?
You have this:
vector<node *> children;
That is fine, it's a vector of pointers to nodes. You do not use new to create it, it is created automatically whenever you have a node. So:
node *createNode(int indexVal)
{
node* n = new node();
n->index = indexVal;
return n;
}
The node has sol and children vectors directly inside it.
Regarding
vector<int>* children = new vector<int>;
and
vector<int> *children = new vector<int>;
They are the same. Both are declaring a pointer to a vector< int>. The only difference is the position of the *. Some people think it is more readable when the * is closer to the type name. Others prefer the * closer to the variable name.
Although I prefer the first one, which puts the * closer to type, the second one is more correct because in C++ the parser associates the * with the variable and not with the type. Thus one could declare the following:
vector<int> *ptr1, var2, *ptr2, *ptr3, var3
This would declare variables ptr1, ptr2 and ptr3 as being pointers to vector< int> while var2 and var3 would be normal variables. If you use the first writing style and write:
vector<int>* ptr1, var2, ptr2, ptr3, var3
Believing that all variables would be pointers, you would be wrong. Only ptr1 would be a pointer and all the others would be normal variables.
Now this
vector<node*> children = new vector<node>;
Is a completely different thing. While on the first two you're declaring a pointer to an array of ints, on the third one you are declaring an array of pointers to int. Also, note the typo you made on the new where you forget the *. To work, it would need to be (note the * at the end)
vector<node*> children = new vector<node*>;
Regarding your code, it seems that sol is the data stored in the node and children contains the pointers to the other nodes. So I believe in this case the following is correct
struct node{
int index;
vector<int> sol;
vector<node *> children;
};
And here
node *createNode(int indexVal)
{
node* n = new Node();
n->index = indexVal;
/* This is wrong and unecessary. As sol is not a pointer, when
you do a new above, the new already allocates the sol so that
you don't need to allocate again here */
vector<int>* soll = new vector<int>; // remove this
n->sol = soll; // not needed
/* Now here you have some typos. It should be vector<node *> and not
vector<node>* */
vector<node>* childrenn = new vector<node *>;
n->children = childrenn;
return n;
}
I didn't make any comments on the tree itself as you posted just a skeleton code instead of the real one. I assume you know trees and just wanted to know the C++ stuff regarding pointers and vector. If you don't know trees yet, look closer to your code because there are some parts that are not quite right.
The first two declarations are equivalent:
vector<node>* children = new vector<node>;
vector<node> *children = new vector<node>;
They declare a pointer to a dynamic vector.
The third declaration:
vector<node*> children = new vector<node>;
declares a dynamic vector<node*> and assigns a new vector to it, which will result in a compile-time error as the types are incompatible.
Try this out
node *createNode(int indexVal)
{
node* n = new node();
n->index = indexVal;
n->sol = new vector<int>;
n->children = new vector<node *>;
return n;
}
void addChildren(node* curr, node* child)
{
curr->children->push_back(child);
}
I have struct Node in my code defined like this:
struct Node {
Node() : prev(0), left(0), right(0) {}
Node* prev;
Node* left;
Node* right;
char val;
};
I initialize array of Node structer objects like that:
Node** pool = new Node*[10000000];
I thought it will create Node structure objects using defoult constructor, but in fact the arrays seems to be empty. Is there any EFFICIENT way to create immidiately array of 'empty' objects?
You should be using std::vector<>; there is very little reason to use new in C++.
auto pool = std::vector<Node>(10000000);
(Your original code is creating Node*s, not Nodes.)
If for some reason you don't want to use vector, you could use std::unique_ptr<>. That code would be
std::unique_ptr<Node[]> pool(new Node[10000000]);
but you really should use vector.
Also, you can simplify and improve Node:
struct Node final {
Node* prev = nullptr;
Node* left = nullptr;
Node* right = nullptr;
char val = '\0';
Node(const Node&) = delete;
Node& operator(const Node&) = delete;
};
If you are constructing an ast/asg and you do not need linear data structures, you may consider still bulk allocating stuff with an ::std::vector<>, which will potentially give you cache locality.
You can still link individual Node objects via the pointers in your struct. If you then use indices instead of pointers, you can even resize your vector whenever you run out of available objects in your pool.
Node** pool = new Node*[10000000];
constructs an array of Node* rather than Node. What you are looking for is,
Node* pool = new Node[10000000];
which constructs an array of Node. If you actually want an array of Node* then the appropriate initialisation is,
int nObjects = 10000000;
Node** pool = new Node[nObjects];
for(auto i = 0; i < nObjects; ++i) {
pool[i] = new Node();
}
As others have said you likely do not want to use new or C-style arrays if you can avoid it.
I have a simple C++ Node class which contains an array data member of pointers to the same type. This array is dynamically allocated and its pointers should default to null but I'm not sure how to achieve it.
class Node
{
private:
Node *_nextNode[];
string _data;
}
Node::Node( const string &p_data, const int &p_levels ): _data(p_data)
{
//unsure how to initialize the '_nextNode[]' member so that the size of the array is of p_levels and they all default to null pointers
}
class SkipList
{
private:
}
Use a std::vector<Node*>:
Node::Node( const string &p_data, const int &p_levels ):
_data(p_data),
_nextNode(p_levels)
{
this will initialise the elements of _nextNode to nullptrs.
Consider using a smart pointer implementation instead of Node* to manage the destruction of the Node instances for you.
If you have to use a Node* then you need a Node** to point to a list of Node*:
class Node
{
private:
Node**_nextNode;
string _data;
};
Node::Node( const string &p_data, const int &p_levels ):
_data(p_data),
_nextNode(new Node*[p_levels]())
{ //^^ value initialization.
allocates an array of int* containing p_levels elements and value initializes them (sets them to NULL). Node needs to know how many elements are stored in _nextNode so p_levels would require storing also. Destruction:
for (int i = 0; i < _nextNodeElements; i++)
{
delete _nextNode[i]; // delete NULL is safe, a no-op.
}
delete[] _nextNode;
Just to push you toward std::vector again: std::vector<std::unique_ptr<Node>> _nextNode; wouldn't require a hand-written destructor, the default generated one would suffice.
_nextNode = new Node[pLevels];
memset ( _nextNode, 0, sizeof (_nextNode));
Is this what you want? Also you should declare Node *_nextNode[] as Node *_nextNode
And you will also have to include <string.h> for memset
Try using Node **_nextNode istead of Node *_nextNode[].
Node **_nextNode= new (NODE**)[ArraySize];
for (int i = 0; i < rows; ++i) {
_nextNode = NULL;
}
I have this test program. I don't know how to delete struct in the list using iterator.
#include<iostream>
#include<list>
using namespace std;
typedef struct Node
{
int * array;
int id;
}Node;
void main()
{
list<Node> nlist;
for(int i=0;i<3;i++)
{
Node * p = new Node;//how to delete is later?
p->array = new int[5];//new array
memset(p->array,0,5*sizeof(int));
p->id = i;
nlist.push_back(*p);//push node into list
}
//delete each struct in list
list<Node>::iterator lt = nlist.begin();
while( lt != nlist.end())
{
delete [] lt->array;
delete &(*lt);//how to delete the "Node"?
lt++;
}
}
I know how to delete the struct separately. It's like this:
Node * p = new Node;
p->array = new int[5];
delete [] p->array; //delete the array
delete p;//delete the struct
However, when it is pushed back into list, I don't know how to delete it according to the list iterator.
list<Node>::iterator lt = nlist.begin();
while( lt != nlist.end())
{
delete [] lt->array;
delete &(*lt);//how to delete the "Node"?
lt++;
}
You could use the list erase to delete a node from anywhere in between the list.
list<Node>::iterator it = nlist.begin();
advance(it,n); \\n is the node you want to delete, make sure its less than size of list
it = mylist.erase (it);
Alternatively, if you want to delete elements from either ends of the list you can use the
pop_back or the pop_front member functions.
Since you are declaring the list with list<Node> when you do:
nlist.push_back(*p)
it is actually creating a Node() and copying the data from the node you just dynamically allocated but not using the actual pointer. And then you try to delete a pointer from the object that the system will automatically delete:
delete &(*lt); // this causes double free
You need to declare the list like list<Node*> so that the pointer is inserted into the list. Although you should not really deal with this kind of allocation in c++, with a couple of modifications your code should work:
int main()
{
list<Node*> nlist;
for(int i=0;i<3;i++)
{
Node *p = new Node;//how to delete is later?
p->array = new int[5];//new array
memset(p->array,0,5*sizeof(int));
p->id = i;
nlist.push_back(p);//push node into list
}
//delete each struct in list
list<Node*>::iterator lt = nlist.begin();
while( lt != nlist.end())
{
delete [] (*lt)->array;
delete *lt;//how to delete the "Node"?
lt++;
}
return 0;
}
use list.erase
But you are really doing that non-c++ way. You do not need allocate int[5] with new. Writing int[5] does what you want. Your Node type defined in c-way. In c++ you do not need to wrap it with typedef
Sorry if this question has been asked before. On my search through SO I didn't find one that asked what I wanted to know.
Basically, when I have this:
typedef struct node
{
int data;
node *node;
} *head;
and do node *newItem = new node;
I am under the impression that I am declaring and reserving space, but not defining, a pointer to struct node, is that correct?
So when I do
newItem->data = 100 and newItem->next = 0
I get confused. newItem = 0would declare what exactly? Both data and next? The object as a whole?
I'm especially confused when I use typedef. Which part is the macro? I assume node because that's how I call it, but why do I need it?
Finally, what happens when I do:
node *temp;
temp = new node;
temp = head->next;
head->next = newItem;
newItem->next = temp;
I mean, head->next is a pointer pointing to object newItem, so I assume not to newItem.data or next themselves. So how can I use an uninitialized pointer that I described above safely like here? is head now not pointing to an uninitialized pointer?
I am under the impression that I am
declaring and reserving space, but not
defining, a pointer to struct node, is
that correct?
No. You are declaring a pointer, allocating space on the stack for the pointer, and dynamically allocating storage for a node to it it.
Don't confuse yourself by writing stuff like this:
typedef struct node
{
int data;
node * next;
} *head;
The way to write the struct in C++ is:
struct node
{
int data;
node * next;
};
You can now create a pointer:
node * pnode;
which allocates storage for the pointer.
and you can dynamically allocate storage for a node, and make the pointer point to it:
pnode = new node;
or do it all in one:
node * pnode = new node;
Now when you say:
pnode->data = 10;
you are not allocating anything. You are assigning 10 to the member called data of the node instance pointed to by pnode. Of course, if you had given your node a constructor (which you should normally do), you could do it all in one:
struct node
{
int data;
node * next;
node( int n, node * np ) : data( n ), next( np ) {}
};
node * pnode = new node( 10, 0 );
When you define your struct as you did and call new like you did, what you're doing is:
allocate a new struct node on the heap.
allocate space on the stack for newItem and set its value to the address of the new struct you allocated.
You didn't set any values to any of the members of the new struct. If you want that to happen whenever you create a new instance of the struct, you need to define a constructor.
typedef struct node
{
int data;
node *node;
} *head;
This declares node as a struct and defines head as a synonym for node*, so head is a type and not an object.
This makes this illegal: temp = head->next; because -> is not something that you can apply to a type.
new node dynamically allocates a node object and returns a pointer to it. node *newItem = new node; assigns this pointer to newItem. Note, though, that newItem->node (node here is a pointer object and not the type node) is not initialized so is neither null nor points to a valid node object.
This is also illegal because node has no next member.
newItem->next = temp;
I suggest that you choose a naming convention that means that you keep your types and your variables separate. It is somewhat confusing.
node *newItem = new node;
You create:
a new node on the heap (which in your case contains uninitialized values because you omitted the ()
a pointer on the stack, which points to this new node.
newItem->data = 100
simply sets the data member of the newly allocated node to 100.