C++ object declaration confusion? - c++

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

Related

Difficulty to understand linked list implementation in C++

I found this C++ linked list implementation in Geeks for Geeks. For the code Click here
Here from line no. 16->22 it is written
Node *head = NULL;
Node *second = NULL;
Node *last = NULL;
head = new Node();
second = new Node();
last = new Node();
I understand
Three pointers are initialized with value NULL and then later three
instances of the class are created.
But what I don't understand is
Where the class objects are created and
From where the pointers are getting the addresses to point to.
And if I keep any data in private how to access it later then in this implementation because . operator is giving error
Where the class objects are created
The allocating new-expression acquires the memory from the free store.
From where the pointers are getting the addresses to point to.
The new-expression returns the pointer to the object that it created.
how to access it later
By indirecting through the pointer using an indirection operator.

Clarification on passing a pointer by reference

This is kind of silly, but I can't really explain why this is happening. As an exercise, I wanted to reverse a singly-linkedlist and I did this by defining the method:
class solution {
void reverseLinkedList(Node*& head) {
Node* curr = head;
Node* prev = NULL;
while (curr != NULL) {
Node* _next = curr->next;
curr->next = prev;
prev = curr;
curr = _next;
}
head = prev;
}
In my main function, I make the call
solution s;
s.reverseLinkedList(head);
Node* iterator = head;
while (iterator != NULL) {
std::cout<<iterator->data<<std::endl;
iterator = iterator->next;
}
Where I previously defined my head pointer to some linkedlist. The while loop is for printing my linkedlist and the function does it job. This only worked after I passed the head node by reference; I initially tried to pass Node* head instead of Node*& head in the beginning, and it only printed the first element of my linkedlist (and without reversing it). For example, if I didn't pass by reference for a list 1->2->3, I would print out just 1.
I thought passing a pointer would be enough? Why did I get such weird behaviour without passing by reference>
Local variables in C++ (stored in the stack) have block scope, i.e., they run out of scope after the block in which they are defined is executed.
When you are passing in a pointer to the function, a copy of the pointer is created and that copy is what is passed. Once the function is executed, the variables in the function workspace run out of scope. Any non-static Automatic variables created within the function are destroyed.
When you pass in by reference you don't pass in a copy of the variable but you pass in the actual variable, thereby any changes made to the variable are reflected on the actual variable passed into the function(by reference).
I would like to point out that the pointer to the next node is stored in memory and has an address to the location it is stored. So if you want to not pass in by reference you can do this:
Use a pointer to the pointer, which points to the memory location at which pointer variable(address) to the next node is stored
Pass in this to the function (not by reference)
Dereference the pointer and store the new address you want to point to.
I know this is a bit confusing, but look into this small piece of code that adds a node to a linked list.
void addNode(Node** head, int newData)
{
Node* newNode = new Node;
newNode->data = newData; // Can also be done using (*newNode).data
newNode->next = *head;
*head = newNode;
}
I thought passing a pointer would be enough?
void reverseLinkedList(Node* head) // pass pointer by value
// head is a copy here
Passing a pointer by value creates a copy to be used inside the function.
Any changes made to that pointer inside the function is only reflected in the function scope. Since those changes are only reflected in the pointer's copy and not in the original pointer.
Once the pointer (copy) goes out of scope, those changes are "discarded" due to end of life.
Thus, you need a reference.
void reverseLinkedList(Node&* head) // changes made in head will be
// reflected in original head pointer
When you pass a pointer regularly (IE by value) it creates a copy of the pointer. Any changes made to this pointer do not effect the original pointer.
Passing a pointer by reference is sending a reference to that pointer (very similar to passing a pointer to a pointer) and therefor any changes made to that pointer are effecting its 'original' state.
For example:
//WRONG does not modify the original pointer, causes memory-leak.
void init(Object* ptr, int sz) {
ptr = new T[sz];
}
vs
//Correct original pointer is a set to a new block of memory
void init(Object*& ptr, int sz) {
ptr = new T[sz];
}
In
void reverseLinkedList(Node* head)
The pointer is passed by value.
This sounds silly, it's a freaking pointer, right? Kind-of the definition of pass by reference. Well, the Node that's being pointed at is passed by reference. The pointer itself, head is just another variable that happens to contain the address of some other variable, and it's not being passed by reference.
So head contains a copy of the Node pointer used to call reverseLinkedList, and as with all parameters passed by value, any modifications to the copy, pointing head somewhere else, are not represented in the calling function.

Difference between these two types of declaration in c++

for this structure
struct node{
int no;
node *next;
};
what is the difference between these two types of declarations?
node *New=new node;
and
node *New;
node *New=new node;
This is initializing the pointer which is good thing to remember.
Whereas
node *New;
not which is a bad thing as chances of de-referencing it in it's naked form are there.
node *New=new node;
Creates a variable called New and initializes it with pointer, returned by operator new
node *New;
Depends on context, for namespace (global) context creates a variable, initialized by nullptr, or for local creates one uninitialized.
You should always initialize a variable when declaring it so that you know it is a good know state. when working with pointer either grab "new" memory at the time of the pointers creation or use nullptr.
node * New = new node; // Okay. We know New holds a good node and we can call delete on it
node * New = nullptr; // Okay. We know we can delete on it without crashing
node * New; // Bad. We dont know what the state of New is and we can't call delete on it
Both nod *New = new node; and node *New; are invalid declaration types. The reason why it allows the lines at all is because the programmer has declared a keyword as a declared structure. They are both bad lines of code. What you have so far is a pointer to a new structure(but not really). New is a keyword that instantiates an object that is greater in precedence than the current scope of the code block. Whenever an object is made eventually it must be unmade with the delete keyword.

What will get removed if i remove a pointer in c++

If I remove a pointer to an object, what will be removed? Only the pointer or also the object which the pointer points to?
For example:
Assume I have a class with a variable
int *root
If I do the following in a method of that class
int *current = root;
delete current;
Will root also be deleted or only the pointer current?
I think you have a misconception about what delete does: delete deletes an object pointed to by a pointer that was previously allocated with new:
int* p = new int; // Create a new int and save its address in p
delete p; // Delete the int
Note that this does not delete p itself in any way, but only the object p points to! You can still use p like a normal variable, e.g. reassign it.
When you have multiple pointers to a pointee you only need to call delete on one of them.
int* root = new int;
int* current = root;
delete current;
std::cout << *root; // undefined behavior
The behavior of delete is described in ยง5.3.5:
6 If the value of the operand of the delete-expression is not a null
pointer value, the delete-expression will invoke the destructor (if
any) for the object or the elements of the array being deleted. In the
case of an array, the elements will be destroyed in order of
decreasing address (that is, in reverse order of the completion of
their constructor; see 12.6.2).
Yes, root is deleted, but depending of the compiler, current can still contain the address of an unexisting variable. So you have to do this to avoid mistakes :
delete current;
current = 0;
int *pointer = new int;
After this statement pointer would be pointing( pointer would be containing the address ) to a block of memory enough to store integer. What internally happens is some chunk from free store would be assigned allocated status.
When you execute
delete pointer;
That memory is returned back to free store so as to fulfill future needs. But you pointer would be containing the same address. When you execute delete again , it would led to undefined behavior since that block is already returned to free store ( that means you have lost the control over that memory through this pointer )
So, to be on safe side you generally set pointer to 0 after deleting that memory.
pointer = NULL;
In implementation of operator delete there is code which check if pointer is NULL, if it is then it returns. So, it's said that there's no harm in deleting NULL pointer.
I hope I have covered every basics.

Why use **head (and not *head) in RemoveHead(node) function?

In most of the explanations in the book the author insists of using **list passing instead of *list, however as per my understanding I feel there is nothing wrong in *list. Please someone explain me in detail if i am wrong. For example, to delete head of a linked list, the author says the below code is wrong.
void RemoveHead(node *head)
{
node *temp = head-> next; /* line 1 */
free(head);
head = temp;
}
Instead he says the below code must be used
void RemoveHead(node **head)
{
node *temp = (*head)-> next;
free(*head);
*head = temp;
}
In your first example:
head = temp;
Does nothing outside the function, it only sets the local variable head to temp inside the function. Whatever variable the caller passed in will remain unchanged. The author is correct, you need to use pointers or (better) references (if you're using C++).
Well. When you want to modify a integer variable inside a function, you pass it by reference. That is, you pass its address.
int x = 5;
void modify_value (int* x)
{
(*x) = 7; // is not 5 anymore
}
With pointers is the same. If you want to modify a pointer. You have to pass it by reference. That is, you have to pass its address. Which is a pointer to a pointer.
int* ptr_x = &x;
void modify_pointer (int** ptr_x)
{
*ptr_x = NULL; // is not &x anymore
}
Author is right. ** is effectively pass by reference (i.e. you can change 'head').
In your version (pass by value), head remains unchanged in the calling code.
When passing a node* as the argument, you can free, and modify the contents of the memory address pointed by that pointer. However, modifications performed on the pointer itself will not be seen from outside the function, since the pointer is passed by value.
On you second example, since you are passing a pointer to the head pointer, you can actually modify the actual head pointer, not just the memory pointed by it.
So in your second function, when *head = temp; is executed, you are modifying the address to which the pointer passed as argument points to.
Therefore, the author is right.
The author is correct. In your first example, you're modifying a local copy of head - the caller won't notice that anything has changed. head will still have been freed, so you're on track for a crash in pretty short order. You need to pass a pointer to modify the caller's variable.