Use the fields of a struct while also using its address - c++

struct nod {
std::pair<int, int> matrixPos;
nod *anteriorNode;
nod(std::pair<int, int> matrixPos)
{
matrixPos = matrixPos;
anteriorNode = nullptr;
} //this is for the first node
nod(std::pair<int, int> matrixPos, nod* anteriorNode)
{
matrixPos = matrixPos;
anteriorNode = anteriorNode;
}
};
void expandNode(std::queue<nod> &coada, int **matrice, nod& nodToExpand)
{
if (matrice[nodToExpand.matrixPos.first-1][nodToExpand.matrixPos.second] == 0)
{
nod newNode = nod(std::pair<int, int>(nodToExpand.matrixPos.first - 1, nodToExpand.matrixPos.second), nodToExpand);
}
}
I have some nodes that I need to link together (so I know which is the parent of each node) while also accessing their values.
I need to acess their matrixPos fields for the values needed in the if statement, while I also need
their address for the field 'anteriorNode'.
How can I do this and what is the most efficient way?

If all you are trying to do is obtain a pointer to nodToExpand from within the expandNode function, you can do so by getting its address. References can be used as if they where the referred object itself, that's their whole deal.
All you need is a good old &nodToExpand.

Related

How to avoid using new operator in C++?

I have a C++ program that creates Huffman codes for all characters in file. It works good, but I want to create nodes without using new operator because I know that you shouldn't use it. I tried using a vector global variable for saving nodes but that doesn't work.
std::vector<Node> nodes;
Node* create_node(unsigned char value, unsigned long long counter, Node* left, Node* right) {
Node temp;
temp.m_value = value;
temp.m_counter = counter;
temp.m_left = left;
temp.m_right = right;
nodes.push_back(temp);
return &nodes[nodes.size() - 1];
}
Edit: I added more code, I did't really explained what doesn't work. Problem is in generate_code(), it never reaches nullptr. I also tried using Node and not Node* but the same thing happened.
void generate_code(Node* current, std::string code, std::map<unsigned char, std::string>& char_codes) {
if (current == nullptr) {
return;
}
if (!current->m_left && !current->m_right) {
char_codes[current->m_value] = code;
}
generate_code(current->m_left, code + "0", char_codes);
generate_code(current->m_right, code + "1", char_codes);
}
void huffman(std::ifstream& file) {
std::unordered_map<unsigned char, ull> char_frequency;
load_data(file, char_frequency);
std::priority_queue<Node*, std::vector<Node*>, Comparator> queue;
for (auto& node : char_frequency) {
queue.push(create_node(node.first, node.second, nullptr, nullptr));
}
while (queue.size() != 1) {
Node* left = queue.top();
queue.pop();
Node* right = queue.top();
queue.pop();
auto counter = left->m_counter + right->m_counter;
queue.push(create_node('\0', counter, left, right));
}
std::map<unsigned char, std::string> char_codes;
Node* root = queue.top();
generate_code(root, "", char_codes);
for (auto& i : char_codes) {
std::cout << +i.first << ": " << i.second << "\n";
}
}
The general answer is of course to use smart pointers, like std::shared_ptr<Node>.
That said, using regular pointers is not that bad, especially if you hide all pointers from the outside. I wouldn't agree with "you shouldn't use new", more like "you should realize that you have to make sure not to create a memory leak if you do".
In any case, for something like you do, especially with your vector, you don't need actual pointers at all. Simply store an index for your vector and replace every occurence of Node* by int, somewhat like:
class Node
{
public:
// constructors and accessors
private:
ValueType value;
int index_left;
int index_right;
}
I used a signed integer as index here in order to allow storing -1 for a non-existent reference, similar to a null pointer.
Note that this only works if nothing gets erased from the vector, at least not before everything is destroyed. If flexibility is the key, you need pointers of some sort.
Also note that you should not have a vector as a global variable. Instead, have a wrapping class, of which Node is an inner class, somewhat like this:
class Tree
{
public:
class Node
{
...
};
// some methods here
private:
vector<Node> nodes;
}
With such an approach, you can encapsulate your Node class better. Tree should most likely be a friend. Each Node would store a reference to the Tree it belongs to.
Another possibility would be to make the vector a static member for Node, but I would advise against that. If the vector is a static member of Node or a global object, in both cases, you have all trees you create being in one big container, which means you can't free your memory from one of them when you don't need it anymore.
While this would technically not be a memory leak, in practice, it could easily work as one.
On the other hand, if it is stored as a member of a Tree object, the memory is automatically freed as soon as that object is removed.
but I want to create nodes without using new operator because I know that you shouldn't use it.
The reason it is discouraged to use new directly is that the semantics of ownership (i.e. who is responsible for the corresponding delete) isn't clear.
The c++ standard library provides the Dynamic memory management utilities for this, the smart pointers in particular.
So I think your create function should look like follows:
std::unique_ptr<Node> create_node(unsigned char value, unsigned long long counter, Node* left, Node* right) {
std::unique_ptr<Node> temp = std::make_unique<Node>();
temp->m_value = value;
temp->m_counter = counter;
temp->m_left = left;
temp->m_right = right;
return temp;
}
This way it's clear that the caller takes ownership of the newly created Node instance.

simple cpp map store and access not working as expected

I have the following code which uses map to insert Nodes into mp according to a key. The class has two functions set and get to insert and access the map respectively.
struct Node {
int value;
int key;
Node(int k, int val):key(k),value(val) {};
};
class Cache {
private:
map<int, Node*> mp;
Node* tail;
Node* head;
public:
void set(int, int);
void get(int);
};
void Cache::set(int key, int value) {
Node newN = Node(key, value);
mp.insert(std::pair<int, Node*>(key, &newN));
}
void Cache::get(int key) {
auto s = this->mp.find(key);
if (s != this->mp.end()) {
Node *nHit = s->second;
std::cout << "Map key = " << s->first;
std::cout << " : Node Key = " << nHit->key;
std::cout << ", value = " << nHit->value << "\n";
}
}
A driver main function implementation is below, which takes input of 2 lines and outputs key and value.
int main() {
int i;
Cache l;
for(i = 0; i < 2; i++) {
string command;
cin >> command;
if(command == "get") {
int key;
cin >> key;
l.get(key);
}
else if(command == "set") {
int key, value;
cin >> key >> value;
l.set(key, value);
}
}
return 0;
}
Input -
set 2 3
get 2
Output -
Map key = 2 : Node Key = 32764, value = -491659096
Note - The output key and value keeps changing and are not fixed with each run.
Why and how is the key and value getting changed for the map here?
You are inserting a pointer to a function-scoped value. When the function set() exits the value newN is destroyed, and the pointer held in the map is invalid.
Either you really want a map with an instance of Node as the value; or you need to use new in set() to allocate your object, but then you also need to remember to delete it. You could use "smart" pointers such as shared_ptr or unique_ptr to help manage this lifetime - though unique_ptr won't get you any advantages over using an instance.
In C++, a piece of data is typically tied to a single location. If that location is a variable in some { block scope; }, then the variable is deleted at the closing }. For instance, the closing bracket of Cache::set deletes newN, and any references to it (including pointers in mp) no longer point anywhere.
C++ has a second option: the lifetime of some data can be controlled by a class. For instance, the int and Node* values you put in mp get deleted along with mp. So rather than storing Node* in mp, you can store Node directly, instead of its address!
The declaration of mp should be
map<int, Node*> mp;
You can insert with
void Cache::set(int key, int value) {
mp.emplace(key, Node(key, value));
}
And then in main you can have
Node &nHit = s->second;
And then you can get members of nHit with . instead of ->.
Your other alternative is to use smart pointers, as Jesper Juhl mentioned. Store std::unique_ptr<Node> in mp if you're using pointers only for polymorphism with virtual methods, and std::shared_ptr<Node> is useful if you want some of your Node objects to be used in several places and mp.
Taking the address of an object with & (e.g. to create Node*) is very useful if you want to just reference an object of known lifetime, and you want to store that reference inside of some other object of a shorter lifetime.
DO NOT use new Node(key, value) except in a smart pointer constructor, unless you're prepared to individually delete every Node* yourself, and never make mistakes.
You have to allocate Node using new. E.g.,
Node *newN = new Node(key, value);
mp.insert(std::pair<int, Node*>(key, newN));
As it is your Node is on the stack and goes out of scope when the function returns.

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).

Pointers and reference issue

I'm creating something similar to structure list. At the beginning of main I declare a null pointer. Then I call insert() function a couple of times, passing reference to that pointer, to add new elements.
However, something seems to be wrong. I can't display the list's element, std::cout just breaks the program, even though it compiler without a warning.
#include <iostream>
struct node {
node *p, *left, *right;
int key;
};
void insert(node *&root, const int key)
{
node newElement = {};
newElement.key = key;
node *y = NULL;
std::cout << root->key; // this line
while(root)
{
if(key == root->key) exit(EXIT_FAILURE);
y = root;
root = (key < root->key) ? root->left : root->right;
}
newElement.p = y;
if(!y) root = &newElement;
else if(key < y->key) y->left = &newElement;
else y->right = &newElement;
}
int main()
{
node *root = NULL;
insert(root, 5);
std::cout << root->key; // works perfectly if I delete cout in insert()
insert(root, 2);
std::cout << root->key; // program breaks before this line
return 0;
}
As you can see, I create new structure element in insert function and save it inside the root pointer. In the first call, while loop isn't even initiated so it works, and I'm able to display root's element in the main function.
But in the second call, while loop already works, and I get the problem I described.
There's something wrong with root->key syntax because it doesn't work even if I place this in the first call.
What's wrong, and what's the reason?
Also, I've always seen inserting new list's elements through pointers like this:
node newElement = new node();
newElement->key = 5;
root->next = newElement;
Is this code equal to:
node newElement = {};
newElement.key = 5;
root->next = &newElement;
? It would be a bit cleaner, and there wouldn't be need to delete memory.
The problem is because you are passing a pointer to a local variable out of a function. Dereferencing such pointers is undefined behavior. You should allocate newElement with new.
This code
node newElement = {};
creates a local variable newElement. Once the function is over, the scope of newElement ends, and its memory gets destroyed. However, you are passing the pointer to that destroyed memory to outside the function. All references to that memory become invalid as soon as the function exits.
This code, on the other hand
node *newElement = new node(); // Don't forget the asterisk
allocates an object on free store. Such objects remain available until you delete them explicitly. That's why you can use them after the function creating them has exited. Of course since newElement is a pointer, you need to use -> to access its members.
The key thing you need to learn here is the difference between stack allocated objects and heap allocated objects. In your insert function your node newElement = {} is stack allocated, which means that its life time is determined by the enclosing scope. In this case that means that when the function exits your object is destroyed. That's not what you want. You want the root of your tree to stored in your node *root pointer. To do that you need to allocate memory from the heap. In C++ that is normally done with the new operator. That allows you to pass the pointer from one function to another without having its life time determined by the scope that it's in. This also means you need to be careful about managing the life time of heap allocated objects.
Well you have got one problem with your Also comment. The second may be cleaner but it is wrong. You have to new memory and delete it. Otherwise you end up with pointers to objects which no longer exist. That's exactly the problem that new solves.
Another problem
void insert(node *&root, const int key)
{
node newElement = {};
newElement.key = key;
node *y = NULL;
std::cout << root->key; // this line
On the first insert root is still NULL, so this code will crash the program.
It's already been explained that you would have to allocate objects dynamically (with new), however doing so is fraught with perils (memory leaks).
There are two (simple) solutions:
Have an ownership scheme.
Use an arena to put your nodes, and keep references to them.
1 Ownership scheme
In C and C++, there are two forms of obtaining memory where to store an object: automatic storage and dynamic storage. Automatic is what you use when you declare a variable within your function, for example, however such objects only live for the duration of the function (and thus you have issues when using them afterward because the memory is probably overwritten by something else). Therefore you often must use dynamic memory allocation.
The issue with dynamic memory allocation is that you have to explicitly give it back to the system, lest it leaks. In C this is pretty difficult and requires rigor. In C++ though it's made easier by the use of smart pointers. So let's use those!
struct Node {
Node(Node* p, int k): parent(p), key(k) {}
Node* parent;
std::unique_ptr<Node> left, right;
int key;
};
// Note: I added a *constructor* to the type to initialize `parent` and `key`
// without proper initialization they would have some garbage value.
Note the different declaration of parent and left ? A parent owns its children (unique_ptr) whereas a child just refers to its parent.
void insert(std::unique_ptr<Node>& root, const int key)
{
if (root.get() == nullptr) {
root.reset(new Node{nullptr, key});
return;
}
Node* parent = root.get();
Node* y = nullptr;
while(parent)
{
if(key == parent->key) exit(EXIT_FAILURE);
y = parent;
parent = (key < parent->key) ? parent->left.get() : parent->right.get();
}
if (key < y->key) { y->left.reset(new Node{y, key}); }
else { y->right.reset(new Node{y, key}); }
}
In case you don't know what unique_ptr is, the get() it just contains an object allocated with new and the get() method returns a pointer to that object. You can also reset its content (in which case it properly disposes of the object it already contained, if any).
I would note I am not too sure about your algorithm, but hey, it's yours :)
2 Arena
If this dealing with memory got your head all mushy, that's pretty normal at first, and that's why sometimes arenas might be easier to use. The idea of using an arena is pretty general; instead of bothering with memory ownership on a piece by piece basis you use "something" to hold onto the memory and then only manipulate references (or pointers) to the pieces. You just have to keep in mind that those references/pointers are only ever alive as long as the arena is.
struct Node {
Node(): parent(nullptr), left(nullptr), right(nullptr), key(0) {}
Node* parent;
Node* left;
Node* right;
int key;
};
void insert(std::list<Node>& arena, Node *&root, const int key)
{
arena.push_back(Node{}); // add a new node
Node& newElement = arena.back(); // get a reference to it.
newElement.key = key;
Node *y = NULL;
while(root)
{
if(key == root->key) exit(EXIT_FAILURE);
y = root;
root = (key < root->key) ? root->left : root->right;
}
newElement.p = y;
if(!y) root = &newElement;
else if(key < y->key) y->left = &newElement;
else y->right = &newElement;
}
Just remember two things:
as soon as your arena dies, all your references/pointers are pointing into the ether, and bad things happen should you try to use them
if you ever only push things into the arena, it'll grow until it consumes all available memory and your program crashes; at some point you need cleanup!

Create std::list of value instead of std::list of pointers in recursive function

I have this class:
class obj
{
public:
obj()
: parent(nullptr),
depth(0)
{ }
obj* parent;
list<obj> children;
int depth; // Used only for this example
};
And to fill my data structure I use a recursive function like the following:
void recursive(obj& parent)
{
if(parent.depth == 1)
return;
obj son;
son.parent = &parent;
son.depth = parent.depth + 1;
recursive(son);
parent.children.push_back(son);
}
In this way for example:
obj root;
recursive(root);
If you pay attention you can see that if the test in the recursive funcion had been:
if(parent.depth == n)
return;
with n >= 2 this code will not work (the stored address of the parent of the "grandson" root->son->son - and so on - will be not a valid address once you exit the recursive function).
One way to solve this problem is use a list of pointers (list<obj*> children) instead a list of value:
void recursive(obj& parent)
{
if(parent.depth == 2)
return;
obj* son_ptr = new obj();
son_ptr->parent = &parent;
son_ptr->depth = parent.depth + 1;
recursive(*son);
parent.children.push_back(son_ptr);
}
Is there another way to do the same work and store the objs in a list of value instead of in a list of pointers?
Isn't it just a matter of fixing the address of the objects before you start creating further children? To do that, put them into the children list first, then recurse...
void recursive(obj& parent, int n)
{
if (parent.depth == n)
return;
obj son;
son.parent = &parent;
son.depth = parent.depth + 1;
parent.children.push_back(son);
recursive(parent.children.back(), n);
}
You might consider storing unique IDs in the objs, such that the instance of the obj doesn't define the represented object's identity but rather its ID does. If you do this, you could potentially store the ID to link related objs instead of storing pointers.
For instance, you could change the obj class to include an int field id:
class obj {
public:
obj()
: parent(nullptr),
depth(0)
{
// Not thread-safe; would need to get protected if multi-threaded
id = nextId++;
}
static int nextId;
int id;
int parentId;
list<int> childrenIds;
int depth; // Used only for this example
};
Whenever you construct a new obj to represent a new logical "thing", you can assign a new, unique value to the id field. When you want to establish a relationship between objs that represent related "things", you can--for instance--use a parentId field instead of a parent pointer field:
void recursive(obj& parent)
{
if (parent.depth == 1) {
return;
}
obj son;
son.parentId = parent.id;
son.depth = parent.depth + 1;
recursive(son);
parent.childrenIds.push_back(son.id);
}
This requires more work when you want to follow the link: instead of following the pointer to the parent obj, you'd instead need to look up the obj in some global obj list you maintain (searching for the parentId in question).
Of course, this really depends on what these objs are really representing, and the broader goals you're trying to accomplish...