Confusion about node pointer assignment - c++

My code looks like this:
#include <iostream>
struct Node {
double data;
Node* next;
};
int main(){
Node* a;
a = new Node;
}
I am having a hard time understanding why the assignment would work for a pointer. Because a is type Node* but the new node is type Node.
At the beginning of my class, I was taught that pointer assignment needs to always be an address.
For example:
int * x;
int y = 5;
This would be allowed:
x = &5;
But this wouldn't:
x = y;
So, by that same logic, shouldn't the assignment of Node* a; be:
a = &(new Node);
Instead of:
a = new Node;
?

When you call new, it creates a new object and returns a pointer to that object. It is quite common to store that pointer in a pointer variable. You would use & new(...) if it returned a reference to the newly-created object. But it doesn't.

but the new Node is type Node.
is absolutely wrong. This is not Java. new Node returns a pointer to a freshly allocated on heap Node.

First of all, every assignment requires correct type. Either you provide left argument of the exact same type as the variable you assign to, or of a type you can convert from. E.g.
int x = 5; //here x is a type of int and 5 is also an int
or
double w = 3; //here w is a type of double and 3 is again int but int can be converted to double
in contrary
int z = 3.2; //won't compile because 3.2 is a float and floats have to be explicitly casted to ints.
Now, with your code, Node* is a type you read as Node pointer and new allocates memory on heap, creates new object and return its address which in this case is also Node pointer. Types match and everything works.

Related

How to allocate the space without changing address in cpp?

for example I have a struct now
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
I first have a pointer, but I do not allocate space for it, so just
TreeNode* p;
I want to allocate the space later, for example, in the other function, like below
void allo(TreeNode* p, int val){
p = new TreeNode(val);
}
allo(p,5);
// I want to get the original p here
But this new method change the address of the original p, which I could not trace it anymore. So is there a method to allocate without changing the address? The limitation is that I want to separate the definition and the allocation, just like above, for example, define outside a function and allocate inside the function.
You need to pass the parameter by reference, if you want to manage this pointer outside this function. Otherwise a copy of the pointer is passed to the function allo. This copying changes the pointer.
Try like this (if I understand the essence of the question):
void allo(TreeNode*& ptr, int val)
{
ptr = new TreeNode(val);
}
First of all:
You should NOT use raw owning pointers but smart pointers like std::unique_ptr<> or std::shared_ptr<> or RAII containers.
Your function allo() will do nothing to the pointer you pass to it because it takes the pointer by value (copy) and there is no way allo() could magically alter the adress of the pointer you pass it nor it's value. All that gets changed is the value of the parameter p which is local to your function, so the memory allocated effectively leaks.
Either, pass the paramter by reference so it can be altered within the function:
void allo(TreeNode* &ptr, int val)
{
ptr = new TreeNode(val);
}
TreeNode *p{ nullptr }; // you shouldn't leave pointers uninitialized
// ...
allo(p, 42);
or return a value:
TreeNode* allo(int val)
{
return new TreeNode(val);
}
// ...
TreeNode *p{ nullptr };
// ...
p = allo(42);
In both cases p points to the object allocated in allo() after the function call.

c++ vector of struct init

I am new to C++ and I am trying to initialize a vector of struct as code below.
struct Node{
int x;
Node *p;
int rank;
Node(int x) {
this->p = this;
this->x = x;
this->rank = 0;
}
};
int main() {
vector<Node> disjointSets;
for (int i = 0; i < 50; i++) {
Node a(i);
disjointSets.push_back(a);
}
}
In main, I try to create a Node a each time and push it into vector. But I later find there is an issue that a is always created at the exact same memory location. Therefore, the p, which is supposed to point to each Node itself will point to the last element after the loop. May someone explain why Node a is always created at same memory address and how to solve the issue?
You have undefined behavior, because you haven't defined a custom copy constructor for your Node class.
disjointSet.push_back(a); makes a copy of a. This is using the default copy constructor, which simply does an element-wise copy of all the member variables. So in the copy, p points to the address of the original Node, not itself. But that Node is destroyed when the loop iteration ends, so the pointer is no longer valid. It's implementation-dependent, but pretty common that the loop happens to use the same stack memory for a each time through the loop, so p in all the elements points to that same address, which is no longer a valid Node.
You need to define a copy constructor that sets p to the address of the copy:
Node(const Node &oldnode) {
p = this;
x = oldnode.x;
rank = oldnode.rank;
}
and a copy assignment operator:
Node& operator=(const Node &oldnode) {
if (&oldnode != this) {
x = oldnode.x;
rank = oldnode.rank;
}
return *this;
}
Your node's are created on the stack. And address which is assigned inside the constructor points to the stack. If you want the Nodes a constant address which doesn't change while they are moved/copied into the container you need to heap allocate them and use a vector of Node pointers. E.g. a vector<std::unique_ptr<Node>>.
You are not using heap memory. Storing the address of a local variable and trying to access it elsewhere is UB. If I'm correct, The answer for "why" the same memory space is taken for each iteration of the loop is implementation defined and in this case, it is reusing the same stack space.

C++ object declaration confusion?

I'm trying to implement a BST in C++, and I came across these two ways of creating a node:
node* z = new node();
z->key = d;
z->left = NULL;
z->right = NULL;
and then this:
node* y = NULL;
node* x = root;
node* parent = NULL;
What is the difference in calling the new operator or not?
EDIT
so for example, whats the difference between:
node* q = new node();
and
node* q;
and why would you choose one way or the other? Is there an advantage for one way or the other?
To answer the question in the comment, yes there is a difference.
When you do node* q = new node() you declare a pointer to a node object, and then at runtime dynamically allocate memory enough for one node object, and calls the default constructor (alternatively, value initializes the object, it depends on the class/struct), and finally you assign the pointer to the newly allocated object to q.
When you do node* q; you just declare a pointer to a node object, and that's it. What the pointer will be pointing to depends on where you declare the pointer: If you declare it as a global variable, it is initialized to zero, and becomes a null pointer; If you declare it as a local variable its value is indeterminate, and will in reality seem to be random. Neither is a valid pointer, and dereferencing it will lead to undefined behavior. There is also a third alternative, and that's where you declare node* q; as a member variable in a class or struct, then the initial value depend on how the class/structure is created and initialized (for example if the structure is value initialized, if there's a constructor that initializes it, etc.).
I'm pretty sure (Someone correct me if i'm wrong), using the new operator allocates dynamic memory for that variable. The variables will most likely already have some garbage value assigned to them that gets overridden when you assign a new value to them. Whereas assigning it NULL just assigns it whatever the NULL value is (probably 0000000).

difference b/w **ptr and *ptr

The basic knowledge i have about pointers is that they point to a memory location and that they can be used for changing and extracting the values stored at that address.
for eg.
int a=5;
int *b;
b=&a;
Now here b points to the memory location of a.
cout<<*b; //gives the output 5
cout<<b; //outputs the address of a.
Basically for the purpose and passing the values by reference in functions and in data structures such as linked list and trees.
main()
{
node *head=NULL;// A pointer head of type node structure
add(&head,2); //adds the value to linked list
}
void add(node**head,int data)
{
//adds value into node
}
Can any one tell me why the &head has been received as **head in the add() function.
Also, what difference would it have made had it been received as *head?
when i print the value of **head it gives me a compiler error.
type of head is node*, when you get address of node* (&head), type of it is node**.
Difference between node** and node* is same as int* and int. One of them defines a pointer to other type.
add method gets a pointer because it might change the value of head. if *head is NULL, it should create a new node and assign head to address of this new node. if it inputted just node head, assigning head = malloc(...) wouldn't work since c is pass by value and it just assigns the "head" defined within the function, not head in the main. but if gets the address of the head in the main, it can freely alter it by accessing it like *head = malloc(...)
head is a pointer so you can't really print its value (well, you can if you cast it but it wouldn't be anything meaningful). You probably need to cast it
int *p; // p -> is a pointer to an int, *p -> integer contained in address pointed by p.
similarly
int **p2; // p2 -> a pointer to a pointer to an it, *p2 -> pointer to a int, **p2 int.
If you are confused, you can remember it as a covering rule. If you want to know what *p is, just cover *p ( we have int so it is an int ), if you to know what *p2 is, just cover it ( we have int * meaning it is a pointer to an int ).
This is my answer to another question: https://stackoverflow.com/a/20818342/2805305
The question was about an error the op got, but in my answer I explain exactly what you need to know.

Passing pointer to a function in C++

I wrote the following piece of code
#include <iostream>
using namespace std;
void temp (int * x)
{
x=new int [2];
x[0]=1;
x[1]=2;
}
int main()
{
int *ptr;
temp(ptr);
cout<<ptr[0]<<endl;
cout<<ptr[1]<<endl;
return 0;
}
Running it gives seg fault, so is the memory allocation which happens inside temp function local to function? The memory gets deallocated while returning from temp? I know, that to solve this problem, I need to pass pointer to pointer ptr, but still, why exactly does this thing not work?
To alter something in a function in C, you need to pass a pointer to it. In this case, you want to alter a pointer, so you need a pointer to a pointer:
void temp (int** x)
then in the function use *x where you now have x (you will need (*x)[n], as *x[n] means something else)
Then call temp with:
temp(&ptr);
This should solve it in C, and will work in C++.
In C++, you could also pass a reference to a pointer:
void temp(int*&x)
which will allow the syntax you have already to be used unchanged.
Think about this code
void temp(int x)
{
x = 2;
}
int main()
{
int y = 3;
temp(y);
cout << y << '\n';
}
What the output going to be 2 or 3? Of course it's three. Now what's the difference between this and your example? Nothing at all. Unless you use a reference everything in C++ is passed by value. x is a copy of y, so changes to x never affect y. This is true whetever the types involved, its true of ints and its true of pointers.
C++ answer:
You are passing the int* argument into temp by value. This means that you are copying ptr into the function, and the pointer x is a completely separate object. You then assign the result of new int[2] to this copy, but the ptr in main is left unaffected. To be able to modify the pointer passed as an argument, you need to take it by reference:
void temp (int*& x)
{
// ...
}
This means that x now refers to the pointer that is passed as an argument. The alternative solution here is to return an int* instead:
int* temp()
{
int* x = new int [2];
x[0]=1;
x[1]=2;
return x;
}
int main()
{
int *ptr = temp();
// ...
}
However, the caller of temp might be unclear about the ownership of the int object. They need to delete[] it, but this isn't made explicit in the interface. Instead, you can return a std::unique_ptr.
int *ptr;
You created an automatic variable here and you passed it to
temp(ptr);
This is pass by copy so x will get the value of ptr and x scope is within the temp function. It is an automatic variable in that scope.When you return from temp its value is lost.
Now, the memory allocated and pointed to by x is in no way reflected to ptr in main. (They are not connected)
You need to do temp(int*& ptr) i.e. pass by reference. Or temp(int** ptr) i.e. pass by address
Note: You have a memory leak in your temp
You need to pass a ** because you are allocating x inside of your function.