How to initialize an array instance of the class within it self? - c++

I want to be able to create an array of Nodes, within a constructor of Node. However i am getting some kind of heap error.
I wrote a Node class with a constructor trying to instantiate Node array with new.
class Node
{
private:
Node* nodes;
int max_size;
int current_size;
public:
Node()
{
max_size = 10;
current_size = 0;
nodes = new Node[max_size]; // Error is here*
}
};
I am hoping to create an object that creates 10 instances of that object within a constructor. As I am writing this i realized that this will create an infinite loop. Those 10 will create another 10 each, and so on. How should i go about solving this? Should i make a double pointer?

If you try to instantiate new Node objects in the Node constructor you will keep making recursive calls to the constructor and run out of memory. You are trying to create a node, which creates 10 nodes, and each of those create 10 nodes, and so on.
If you want to just allocate space for max_size nodes, you will need to use a double pointer if you don't want to use std::vector.
class Node {
private:
Node** nodes;
...
public:
// Constructor
Node() {
...
nodes = new Node*[max_size];
}
};
Outside the constructor you can populate that array with new Node objects through a separate function.

Related

why is a double pointer being used to create a Queue?

I have two classes Node and Queue. In Queue constructor we need to create an array of type Node in the heap. My question is why we should use a double pointer Node **Q and then create an array Q=new Node*[size] like this when we could have done created an array of Nodes with a single pointer? like Node *Q and Q = new Node[size]
class Node
{
public:
Node *lchild;
int data;
Node *rchild;
};
class Queue {
private:
int front;
int rear;
int size;
Node **Q;
public:
Queue(){front=rear=-1;size=10;Q=new Node*[size];}
Queue(int size){front=rear=-1;this->size=size;;Q=new
Node*[size];}
void enqueue(Node *x);
Node *dequeue();
int isEmpty(){ return front==rear;}
};
First, let's make it clear that we are looking at two distinct data structure:
A binary tree, which is defined by Node objects.
A queue backed by a fixed-size buffer (possibly it's a ring buffer).
There is also an algorithm that uses these data structures. Based on one of the comments, this algorithm builds a binary tree from the queued nodes. In other words, the algorithm want to modify the original Node objects - it doesn't want to modify copies of them.
So the reason to allocate an array of Node * is so that the queue doesn't have to copy the Node objects. Instead, the pointer that is enqueued is the very same pointer that is later dequeued. This allows the linking algorithm to operate on the original nodes, and therefore to have the desired effect.

Copy constructor for a vector of pointers

I'm trying to create a node class that contains a vector of pointers. Here's my code:
node.h:
#ifndef NODE_H
#define NODE_H
class node
{
public:
vector<node*> next;
void add_arc(node & a)
string some_string;
#endif
node.cpp:
void node::add_arc(node & a)
{
node *b = &a;
next.push_back(b); //only copyies nodes
}
main.cpp:
int main()
{
vector<node> nodes;
node a;
node b;
node c;
a.somestring = "a";
b.somestring = "b";
c.somestring = "c";
a.add_arc(b); //a should point to b
a.add_arc(c); //a should point to c
nodes.push_back(a);
nodes.push_back(b);
nodes.push_back(c);
cout << nodes[0].next.size() << endl; // prints "2", works fine
cout << nodes[0].next[0]->some_string << endl; //empty
}
I thought it would be as easy as just overloading push_back:
void push_back(vertex * pointer)
{
next.push_back(pointer);
}
But I think I really need a copy constructor, or some other method to make this work. How would I go about doing this for a vector of pointers?
Edit: I guess I didn't explain it well. Look at the answers in this question:
Segmentation fault when accessing a pointer's member function in a vector
Making 'a' a reference did not work for me
It works...
Your code generates as expected the correct output (see online demo):
2
b
...However this design is not future proof
However this result is related somehow to luck, because in your code snippet:
the nodes in the nodes vector are copies of the original object including all their pointers
the local objects a, b, c to which these pointers point still exist
However in more complex code, you'd quickly end up with dangling pointers.
Imagine:
Bad example 1: you create a graph, keeping all the nodes directly in a vector of nodes. You then add the first arcs between the nodes. As soon as you'll add a new node to the vector, reallocation might occur and you'd risk to see all your next pointers invalidated.
Bad example 2: you initialise a graph like you did, but in a function called by main. In this case, as soon as you return from this function, all the local nodes get destroyed and the vector's node will point to objects that do no longer exist. UB guaranteed !
How to improve ?
Your design fails to recognize that the nodes all belong to the same graph.
There is a quick and dirty way out: always create the node from the free store, and store them in a vector<node*>.
vector<node*> nodes;
node *a = new node("a"); // Imagine a node constructor
node *b = new node("b");
a->add_arc(b); //change signature, to accept a pointer
nodes.push_back(a);
nodes.push_back(b);
There's a better approach: improve further the previous approach, but use shared_ptr<node*> to make sure that nodes that are no longer referenced (neither by a vector of nodes, nor by an arc) are destroyed automatically.
There's an even better approach: encapsulate the nodes in a class representing a graph. In this case, you could consider using a vector<nodes> and replace the pointers in next, by indexes of the target nodes in the vector. No pointer, but perfect copy of graphs will be much easier. And no more memory management hassle.
class node // just to give the general idea
{
public:
vector<int> next; // not usable without the graph
void add_arc(int a)
string id;
};
class graph {
vector<node> nodes;
public:
void add_node (node a);
void add_arc (string from, string to);
node& operator[] (size_t i);
...
};

Creating a non-binary tree structure in C++

I need help creating a non-binary tree structure. This structure must contain a class node with as many pointers to node as a the node needs. This is where I get confused.
Here is my class node:
class nodo{
public:
int id;
char info[255];
nodo **son,*father;
nodo()
{
strcpy(info,"");
son=(nodo*)malloc(sizeof(nodo));
}
};
As far as I understand, each time I need a new son pointer I must do the following code:
son=(nodo*)realloc(sizeof(nodo)*t)
t being the number of nodes I want to add plus 1. I canĀ“t seem to understand how to access the pointers. For example, I've already added 2 sons and I want to access the second one, how should I do it?
Is there any other approach to the problem?
Any help will be thanked.
You're writing C++, not C. Don't try to re-implement your own dynamic array from the ground up. The standard library already has std::vector to handle that for you.
class nodo{
public:
int id;
std::string info;
nodo *parent;
std:::vector<nodo *> children;
nodo(nodo *parent) : parent(parent)
{
}
void add_child(nodo *child) { children.push_back(child); }
};
You're trying to dynamically create an array of child pointers for each node. This approach is fine as long as you know how many children the node will have beforehand.
Your constructor should look something like this:
nodo(int numsons) {
son = new nodo*[numsons];
}
This will allocate an array of child nodes, which you will need to delete in the deconstructor.
If you don't know how many children the node will have beforehand (when you call the constructor), you should use a vector.

c++ weird behavior of constructors when using vector as the class private variable

First of all I am sorry for this silly question, but I am new to the world of C++ and I am used to Java and Python.
I would like to ask how are constructors supposed to work in C++. I would expect that if I assign some value or sub-object to my instance then it will not be deleted by another constructor?
Particularly my problem is following:
I have class Tree that looks like this:
class Tree {
Node * const first;
Node * last;
std::vector<Node *> nodesVector;
unsigned int nodes;
public:
Tree(Node * const root) : first(root){
nodes = 1;
nodesVector.push_back(root);
}
}
And then I have class RRTStar that looks like this:
class RRTStar {
Tree * tree;
Node * root;
const double RADIUS;
public:
RRTStar(const Point & point, double radius) : RADIUS(radius){
Node n;
n.point = point;
unsigned int zero = 0;
n.id = zero;
n.cost = 0;
n.parent = NULL;
this->root = &n;
Tree t = Tree(this->root);
this->tree = &t;
}
}
As you can see there is always appended one value to the vector from the Tree's constructor which is called from RRTStar constructor. When I go through debug I can see that there is really added the Node n to the vector, but unfortunately it is then somehow deleted after the RRTStar constructor finishes.
So my question is what am I doing wrong that vector or it's content of the tree instance is deleted?
These two lines look most suspect:
this->root = &n;
this->tree = &t;
They are taking the address of a local variable, which will be destroyed when the constructor completes. Any use of those pointers outside of the constructor will be UB.
You need to dynamically allocate them using new, and make sure your destructor, copy constructor, and assignment operator handle them appropriately.

c++ store items into an array

I have this code that in my mind, it recieved an item called Vehicle and it has to store it in an array called Node. This is the code related to this part of the program:
void Table::process(Vehicle v, int cont) {
char a='A'+cont;
putVehicle(a,v);
Node.a_v[cont]=v;
if(cont==0) a_surt=v.rowVehicle();
}
This is how I have the array on the private part of Table.h:
struct Node{
Vehicle a_v;
};
The error I get is:
error: expected primary-expression before '.' token
I have the includes I need, but everytime I type this: Node.a_v It gives me that error.
Any advice?
If you want to use a struct, you need to declare a Node before using it. Also, the struct needs to contain an array (or better, look into vectors for more flexibility).
struct Node {
Vehicle[10] a_v; // 10 is max number of Vehicles in array
};
Node myNode;
myNode.a_v[cont] = v;
Remember that if you want to keep this Node around and put more things in it, it needs to be declared in the right scope. For example, to have your process function add a Vehicle to a Node that exists outside of the function process, you could something like this:
void Table::process(Node n, Vehicle v, int cont) {
char a = 'A'+cont;
putVehicle(a,v);
if (cont < 10) {
n.a_v[cont] = v;
}
if (cont == 0) a_surt = v.rowVehicle();
}
It kind of looks like you're just trying to use an array. In that case you're looking for something like this:
// This would go somewhere in your program. Again, 10 is just an example.
Vehicle vehicleArray[10];
// Send this array to this function
void Table::process(Vehicle[] vArray, Vehicle v, int cont) {
char a = 'A'+cont;
putVehicle(a,v);
if (cont < 10) { // In a real program, don't hard-code array limits.
vArray[cont] = v;
}
if (cont == 0) a_surt = v.rowVehicle();
}
You should use Node object to get access to the a_v variable. This line
Node.a_v[cont]=v;
Is incorrect. You should do something like that:
Node n;
n.a_v[cont]=v;
everytime I type this: Node.a_v It gives me that error.
Node is a type; types define the structure of a objects, but they do not have fields of their own (except the static fields, which belong to all instances at once; they are accessed differently anyway).
In order to use a . or -> operator, you need an instance of a Node, like this:
Node x;
x.a_v = ...
It is not clear in your case from where the Node instances should be coming, though. In order to access them, you would need to either pass them in as parameters, or make them available statically/globally (not recommended).
Okay, so Node is NOT the name of your array. It's the name of a user-defined type that is supposed to contain an array. Your Node, however, does not contain an array. It contains one Vehicle, named a_v. I assume a_v is supposed to represent an Array of Vehicles. Therefore, you need to allocate the array. Something like this:
struct Node {
Vehicle a_v[AMOUNT];
};
If you don't know at compile-time how large you want your arrays to be, then they must be dynamically allocated, like this:
struct Node {
Vehicle* a_v;
Node() {
a_v = new Vehicle[AMOUNT];
}
};
If it's dynamically allocated, then it must also be deallocated:
struct Node {
Vehicle* a_v;
Node() {
a_v = new Vehicle[AMOUNT];
}
~Node() {
delete[] a_v;
}
};
AND if it's dynamically allocated, you need to add provisions for copying or disable copying:
struct Node {
Vehicle* a_v;
Node() {
a_v = new Vehicle[AMOUNT];
}
~Node() {
delete[] a_v;
}
// Disable copies (with C++11 support):
Node(const Node&) = delete;
Node& operator=(const Node&) = delete;
// Disable copies (without C++11 support) by making them private and not defining them.
private:
Node(const Node&);
Node& operator=(const Node&);
};
Then to access one of the Vehicles, you'd need to do so like this:
Node n; // Declare a node, which contains an array of Vehicles
n.a_v[cont] = v; // Copy a Vehicle into the array of Vehicles
Note, however, that if you declare the Node instance in this function, then it is local and it will go out of scope as soon as your function ends. You need to declare the Node instance as a member of your Table if you want it to persist past the function call.
class Table
{
private:
Node n;
};
Lastly, as others have suggested, I'd highly recommend that you read a C++ book to learn C++. My personal recommendation is this book (5th edition, don't buy 6th or 7th - the author of those editions is terrible).