passing struct by reference in c++ doesnt update the value - c++

i am passing a struct by reference to one function of a class treestr and storing it there in a vector.
Then passing the same struct by reference to another function and performing some computation on data member of struct. This data member gets updated in the original struct but not in the ones stored in the vector.
(Sorry for any mistakes, new to c++, new to stack overflow). Please help.
//Structure description
Struct point{
int x;
int y;
int cal{0};
};
Struct node{
point p;
int data; //value to be updated by func
};
int main(){
treestr * tree= new treestr(); //create object
int i=0,n=100;
vector<node> nob;
while(i<=n){
p={1,5}; //some values input by user
node n={p,i};
nob.push_back(n)//storing the struct node objects seperately in a
//vector
treestr->insert(n); //inserting into tree class
i++;
}
//calling func to do some computation on the struct objects inserted
for(i=0;i<n;i++){
int x=tree->func(nob[i]);
cout<<x.cal; //getting updated values from the function
}
for(i=0;i<N;i++){
tree->func2(nob[i]);
}
return 0;
}
//class description
class treestr{
vector<node> buck;
insert(node& n){
buck.push_back(n);
//store nodes
}
func(node& n){
//calculations
return n.cal; Value got updated in main.
}
func2(node &n){
int val1=n.cal; //this assigns updated value
int val2=buck[i].p.cal; //this assigns 0(default value)
if(val1==val2){ //never matches, val2 is 0 for all objects, val1 is
//not after getting updated
//do something
}
}
};
The cal gets updated in the main function but not in the class where I have stored. Please ignore grammatical and syntactical mistakes, the code returns correct output however this is something that I need to improve my code.
Any possible reasons??

Try changing
node n={1,5,0}
to
node * n;
node -> x = 1;
node -> y = 5;
node -> cal = 0;
From what I know of pointers you need to assign each value individually.
Also
tree->insert(n)
needs to be
tree.insert(n)
Another thing
int node.cal=tree->func(n);
Not sure what this is supposed to do, but I know it won't work. 'int' needs to be before a variable name. When accessing cal from node your call needs to be an -> and when accessing func from tree it needs to be a .

Related

C++ Vector not changing value after being altered in a method

I'm trying to create a class for a node in a directed graph (I don't know much about them so forgive if I've messed up any terms).
Whenever I add a pointer to n2 to n1's outNodes vector, I want a pointer to n1 to be added to n2's inNodes vector. I hope that made sense and here is my code.
#include <iostream>
#include <vector>
class Node {
private:
static int nextId;
int id;
std::vector<Node*> ptr_outNodes;
std::vector<Node*> ptr_inNodes;
public:
Node() {
id = nextId++;
}
int getId() {
return id;
}
void setInNodes(Node n) {
ptr_inNodes.push_back(&n);
}
void setOutNodes(Node n) {
ptr_outNodes.push_back(&n);
n.setInNodes(*this);
}
std::vector<Node*> getOutNodes() {
return ptr_outNodes;
}
std::vector<Node*> getInNodes() {
return ptr_inNodes;
}
};
int Node::nextId = 0;
int main() {
Node n1;
Node n2;
n1.setOutNodes(n2);
std::cout << n2.getInNodes().size();
return 0;
}
As you can see, I have it set to return the size of n2's inNodes. When I run the program I see that it's size is 0. If I print out the size within the setInNodes method, I get the result 1 which is odd to me. Also, if I change my main function to this:
int main() {
Node n1;
Node n2;
n1.setOutNodes(n2);
n2.setInNodes(n1);
std::cout << n2.getInNodes().size();
return 0;
}
I get the result 1. Adding that line shows that the function is working, so I believe something is going wrong when I call setInNodes() from setOutNodes(). I've been staring at this for the past half hour, so if someone could help me that would be great, thanks!
You are providing the methods setInNodes and setOutNodes with copies of the original Node object. The pointer you're pushing into the vector is the address of that copy, not of the original object.
To push the address of the original Node object, you need to pass a Node-pointer to the function.
Code:
... // Your Node class code
void setInNodes(Node *n) {
ptr_inNodes.push_back(n);
}
void setOutNodes(Node *n) {
ptr_outNodes.push_back(n);
n.setInNodes(this);
}
...
// in the main function:
n1.setOutNodes(&n2);
n2.setInNodes(&n1);
In your code :
void setInNodes(Node n) {
ptr_inNodes.push_back(&n);
}
void setOutNodes(Node n) {
ptr_outNodes.push_back(&n);
n.setInNodes(*this);
}
You're passing Node by value (its a temporary). Then you're adding the pointer to the temporary to you're vector. When you're function (setxxx) goes out of scope, the temporary is destroyed, and hence the stored pointer is a pointer to an invalid object. Accessing/dereferencing the pointer after the function exits is undefined behavior (ie the program can do anything).
As mentioned elsewhere you can either pass in a pointer or a reference.
void setXxNode(Node& node)...
Passing by reference would be my choice, as it requires a value (shows intent). One then adds the address of the reference to the vector, but note that the lifetime of object referred to must exceed that of the object that now holds the pointer.

Memory allocation In Tree

Hello everyone i wish you are having a great day, i have a problem with allocation memory for my tree with some code i think it's easier to explain and understand.
#define H 7
class Node{
public:
int node_number;
int depth;
int value;
Node* nodes[L];
public:
Node new_node(int node_number,int depth,int value);
void add_node(Node root_node,Node new_node);
void print_node(Node print_node);
};
To create a node my function is here
Node Node::new_node(int node_number,int depth,int value){
Node x;
x.node_number=node_number;
x.depth=depth;
x.value=value;
x.nodes[L]=(Node*) std::malloc(L*sizeof(Node));
return x;
}
and now when i want to add nodes in the node him self like declared in the class i got Segmentation fault (core dumped)
void Node::add_node(Node root_node,Node new_node){
root_node.nodes[0]=&(new_node);
}
My main function
Node root_node;
root_node=root_node.new_node(10,2,23);
Node x;
x=x.new_node(17,19,7);
root_node.add_node(root_node,x);
root_node.print_node(root_node);
Thank you so much
There are few problems here. Firstly you're not actually allocating any new memory. The line in the new_node method
Node x;
is a local variable so it will be destroyed when the method completes, the method then returns a copy of this object on the stack.
Then in the add_node method there is another problem:
root_node.nodes[0]=&(new_node);
This line doesn't call the node_node method, it actually takes the address of the function. Even if it did call the method it would be returning a copy of the object on the stack not a pointer to an object on the heap which is what you need.
Your code doesn't show the definition of L, I'm going to assume that it is a macro definition. Your new_node method should look like this, node the new reserved word, this is where the new object is created on the heap:
Node* Node::new_node(int node_number,int depth,int value){
Node *x = new Node;
x->node_number=node_number;
x->depth=depth;
x->value=value;
// x->nodes[L]=(Node*) std::malloc(L*sizeof(Node));
// not needed if L is a macro and needs correcting if L is a variable
return x;
}
Now this method returns a pointer to a new object on the heap.
Your add_node method will then look like this:
void Node::add_node(Node root_node,Node new_node){
root_node.nodes[0]=new_node(/* Need to add params here! */);
}
However there is a much better way of doing what you want here. You should write a constructor for the Node class like below:
Node::Node(int node_number,int depth,int value)
{
this->node_number = node_number;
this->depth = depth;
this->value = value;
}
This removes the need for the new_node method and means your add_node method will look like this:
void Node::add_node(Node root_node,Node new_node){
root_node.nodes[0]=new Node(/* Need to add params here! */);
}
Hope this helps.
Although there is already a complete answer provided by PeteBlackerThe3rd, I deem it worthy to also provide an answer that does not use any manual memory allocation as this is often the preferred way in C++.
I took the liberty to make some minor adjustments, e.g., when adding a node it is not necessary to provide the depth in the tree as this can be derived from its parent's node.
The struct uses a std::vector which has (at least) two benefits compared to the code provided in the question. First, there is no need to know the maximum number of children nodes during compile time. If you want to fix this during compile time one can easily replace the std::vector by std::array. Second, there is no need to manually free memory at destruction as this is all taken care of by std::vector.
#include <iomanip>
#include <vector>
struct Node
{
// I expect these data members to be constants
int const d_nodeNumber;
int const d_depth;
int const d_value;
std::vector<Node> d_childNodes;
Node() = delete;
Node(int number, int depth, int value)
:
d_nodeNumber (number),
d_depth (depth),
d_value (value),
d_childNodes ()
{ }
/*
* Note that this function does not ask for a 'depth' argument
* As the depth of a child is always the depth of its parent + 1
*/
void addChildNode (int number, int value)
{
d_childNodes.emplace_back(number, d_depth + 1, value);
}
/*
* Just an arbitrarily function to generate some output
*/
void showTreeFromHere() const
{
int const n = 1 + 2 * d_depth;
std::cout << std::setw(n) << ' '
<< std::setw(5) << d_nodeNumber
<< std::setw(5) << d_depth
<< std::setw(5) << d_value << std::endl;
for (Node const &n: d_childNodes)
n.showTreeFromHere();
}
};
The struct can be used as follows:
int main()
{
Node root_node(0,0,0);
// Add two child nodes
root_node.addChildNode(1,1);
root_node.addChildNode(2,1);
// Add six grandchildren
root_node.d_childNodes[0].addChildNode(3,8);
root_node.d_childNodes[0].addChildNode(4,8);
root_node.d_childNodes[0].addChildNode(5,8);
root_node.d_childNodes[1].addChildNode(6,8);
root_node.d_childNodes[1].addChildNode(7,8);
root_node.d_childNodes[1].addChildNode(8,8);
root_node.showTreeFromHere();
}

Please help me get through this unexpected output

This is my sample C++ code for a linked list . This is not actually a linked list but just a dummy program. I get unexpected output for this program.
#include<iostream>
using namespace std;
struct list{
int data;
list *next;
};
void setData(list ob){
int d;
cout<<"enter data"<<endl;
cin>>d;
ob.data=d;
}
void getData(list ob){
cout<<"Data is :"<<ob.data<<endl;
}
int main(){
list node1,node2,node3;
setData(node1);
setData(node2);
setData(node2);
getData(node1);
getData(node2);
getData(node3);
return 0;
}
My input for the code was 2,3 and 4. The unexpected output that I get is -
enter data
2
enter data
3
enter data
4
Data is :2293540
Data is :4201920
Data is :2293608
Edit
struct list{
char data; list next;
}
void main(){
list *start,node1,node2;
//I got stuck on the below two lines
start=(struct list)malloc(sizeof(list)); //Dynamic allocation of memory of size list whose address is stored in start
start=&node1; // start holds the address of node1 which is not dynamically allocated .
I don't understand why is *start given a dynamic address if the second statement overrides it by giving it the memory address of node1 which is in the stack(atlest what I understood).
Because you are passing your linked list by value. To change this, pass by reference.
void setData(list& ob){
int d;
cout<<"enter data"<<endl;
cin>>d;
ob.data=d;
When you pass by value, C++ makes a copy of whatever you pass in. So when you are calling getData, you pass in a copy of a list that has no data in it, so garbage is getting printed.
You need to pass in your list by reference
void setData(list& ob){
int d;
cout<<"enter data"<<endl;
cin>>d;
ob.data=d;
}
You are currently passing in ob by value, so although you are indeed setting the data attribute correctly, you are doing so to the function-local copy of ob, not the original list that you passed into the function.

What is the uses of using a pointer in this specific scenario?

In this scenario, I have a struct Data declared.
struct Data {
string first;
string middle;
string last;
int age;
};
According to my notes, we then create a
vector<Data*> list;
To add items to this list, we have to create a new data pointer and set attributes manually.
Data* variable;
variable=new Data;
list.pushback<variable>
I do not see the merits of using this approach. Why can't we just use this?
vector<Data> list;
To add items to this list, I create a new Data variable, then use
list.pushback<variable>;
Am I right to say both approaches works?
First of all it has to be
list.push_back(variable)
instead of
list.pushback<variable>
The difference is that in case 1 you create a pointer to the variable, which means you only store the adress of variable in the list. This code
#include <string>
#include <vector>
#include <iostream>
using namespace std;
struct Data {
string first;
string middle;
string last;
int age;
};
int main()
{
vector<Data*> list;
Data* variable;
variable = new Data;
list.push_back(variable);
cout << list[0];
cin.get();
return 0;
}
would only return you the address of the place in memory where variable was stored.
So to return some value of variable you could use something like
vector<Data*> list;
Data* variable;
variable = new Data;
variable->setage(5);
list.push_back(variable);
cout << (*list[0]).getage();
cin.get();
return 0;
}
Where *list[0] dereferences the pointers, that means you get the value and not the adress of it.
If you work without pointers instead
vector<Data> list;
Data variable;
list.push_back(variable);
instead, you would store a copy of variable in the list.
So in this case you could directly address variable by something like
list[0].getage()
if you create a getage() function in the struct Data.
If you don't know how to do so, an easy( maybe not the best) way is to add
public:
int getage(){
return age;
}
void setage(int x){
age = x;
}
};
in your struct Data.
It is faster.
For your case, if you were to do
Data variable;
// change properties here
list.push_back(variable);
you would first create a struct Data on the first line, and then you would copy the entire struct when it was pushed back into the list. Since the struct is larger than a pointer to it, doing so is simply not as computationally efficient as just pushing the struct pointer.

vector doesn't work in struct

I have struct like this:
struct element{
char ulica[10];
vector<int> dane[3];
int wolne;
int w;
element *lewy, *prawy, *ojciec;
};
And I'm implementing kind of AVL tree. When key's are the same i need to put some int values to dane (dane[0], dane[1], dane[2] describe 3 different value) so I use
tmp2->dane[0].push_back(number)
EDIT. Here is code where I'm adding a values to this vector, it's half of the function because secod half is about rotations in AVL.
void wstaw_wezel(){
element *tmp2; //tmp2 bedzie ojcem nowo wstawionego elementu
tmp2=korzen;
while(tmp2!=NULL){
if(strcmp(tmp2->ulica, tmp->ulica)<0){
if(tmp2->prawy!=NULL){
tmp2=tmp2->prawy;
}
else{
tmp->ojciec=tmp2;
tmp2->prawy=tmp;
cout<<"Wstawiam pod prawy "<<tmp2->ulica<<endl;
if(tmp2->w!=0) tmp2->w=0;
else tmp2->w=-1;
break;
}
}
else if(strcmp(tmp2->ulica, tmp->ulica)>0){
if(tmp2->lewy!=NULL){
tmp2=tmp2->lewy;
}
else{
tmp->ojciec=tmp2;
tmp2->lewy=tmp;
if(tmp2->w!=0) tmp2->w=0;
else tmp2->w=1;
cout<<"Wstawiam pod lewy "<<tmp2->ulica<<endl;
break;
}
}
else{
cout<<"2 bloki na tej samej ulicy"<<endl;
for(int i=0; i<tmp2->dane[0].size(); i++) cout<<tmp2->ulica<<" "<<tmp2->dane[0][i]<<endl;
tmp2->numery.push_back(tmp->numery[0]);
tmp2->dane[0].push_back(tmp->dane[0][0]);
for(int i=0; i<tmp2->dane[0].size(); i++) cout<<tmp2->ulica<<" "<<tmp2->dane[0][i]<<endl;
tmp2->dane[1].push_back(tmp->dane[1][0]);
tmp2->dane[2].push_back(tmp->dane[2][0]);
tmp2->wolne+=tmp->dane[2][0];
break;
}
}
if(tmp->ojciec==NULL){
korzen=tmp;
return;
}
where tmp2 is a pointer to this struct (I checked adrres where it points and every time it's the same adrres).
Where is problem? If I add new value to vector it is until the loop where i do it ends. Finally instead having fe. 4 values in vector i have one, the last added value. Vector don't add new value to the end, just replacing it.
You declare the initial size of a std::vector in its constructor, so one way you can accomplish this is:
struct element
{
char ulica[10];
std::vector<int> dane;
int wolne;
int w;
element *lewy, *prawy, *ojciec;
element() : dane(3) {}
};
If you don't include the constructor, the initial size of the vector will be 0. In any event, to add an element to the back, just use tmp2->dane.push_back(number); This will add the value in number to the back of the vector tmp2->dane which may result in a change in the amount of allocated memory for the vector instance.
UPDATE: Based on the comment from the OP that he needs three vectors try this:
struct element
{
char ulica[10];
std::vector<std::vector<int> > dane;
int wolne;
int w;
element *lewy, *prawy, *ojciec;
element() : dane(3) {}
};
To add elements to the vectors, simply use tmp2->dane[i].push_back(number) where i is the index of the vector to use, and number is the new number to add to the ith vector, which is the same convention you seem to be using in your code segment above.
Update 2: Based on additional information below, I think a redesign of your data structure is called for. You're mixing the meaning of the various components and by more clearly delineating the functions of the data element and the AVL data structure management, you will be able to more clearly distinguish between the two. So try this instead. Have a data structure specifically for the "value" portion of your tree nodes, as in:
struct house
{
int house_number;
int unique_value0;
int unique_value1;
house(int hn, int uv0, int uv2)
: house_number(hn),
unique_value0(uv0),
unique_value1(uv1) {}
};
template <typename VALUE> struct node
{
std::string key;
std::vector<VALUE> values;
int left, right;
node<VALUE> *leftNode, *rightNode, *parentNode;
};
From here, you create a root node:
node<house> *root;
When you want to add a house to a street, node<house> *s, all you need to do is
s->values.push_back(house(a, b, c));
Of course a better alternative is to use what C++ already has for this. That is, there is a structure in the standard library called std::multimap which does pretty much what you're trying to do. In this case, you can simple declare
std::multimap<std::string, house> myMap;
This probably won't use AVL balancing. It more likely will be a Red-Black Tree, but it's all done for you.
How do you alloc the struct element?, it seems that the vector<int> dane[3]; has been initialized successful, but its inner vector does not been initialised.
try to add a ctor method to the struct element?
struct element
{
char ulica[10];
vector<int> dane[3];
int wolne;
int w;
element *lewy, *prawy, *ojciec;
element()
{
dane[0] = vector<int>();
dane[1] = vector<int>();
dane[2] = vector<int>();
}
};