Difference between 'new' and '=' in relation to pointers - c++

These two pieces of code are creating very different results depending on the compiler and I don't understand why
node *active_node = new node;
vs
node current_node;
node *active_node;
active_node = &current_node;
From my understanding, I am manually creating a node object and assigning it to the active node pointer, same as the dynamic allocation above. However, they produce entirely different results in context of the program

In this code:
node *active_node = new node;
You are allocating a node object in dynamic (heap) memory, and then assigning its address to active_node. The node object will live until the program is terminated, or until you delete it.
In this code:
node current_node;
node *active_node;
active_node = &current_node;
You are allocating current_node in automatic (stack) memory, and then assigning its address to active_node. The current_node object will die when it goes out of scope (end of the function, etc), leaving active_node to point at invalid memory.

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.

What happens to Node* next when deleting that Node in a linked list?

In a linked list that uses
struct Node {
T value;
Node* next;
}
For every used new operator (new Node()), there must be a delete operator.
An example of a destructor for such a list
~LinkedList(){
Node* tmp = head;
while(tmp! = nullptr){
delete tmp;
tmp = tmp->next;
}
}
My question is, what exactly gets "deleted" that allows me to use next pointer
even after delete is used? Does it only delete the value? How does that actually look in the memory?
In C++ when you delete an object on the heap nothing actually gets cleaned up, it just marks the memory as "free". This means that another call to new or malloc may overwrite that memory.
Accessing a deleted pointer is undefined behaviour because their are no guarantees on the data that resides there. I'm not very well versed in how the OS handles memory but I believe it could even be the case that your program no longer owns that page if that was the last item you deleted from that section of memory. If this happened to be the case then dereferencing that pointer will cause a segmentation fault on most desktop OS's.
If you wanted to safely move the head you should assign a temporary value to the next item while the pointer is alive, then you can delete the underlying object from memory.
When a data is deleted the pointer becomes undefined and for sure does not reach to memory it was pointing before, therefore there is no way to call tmp=tmp->next' after deletion.
The proper destructor declaration would be:
~LinkedList()
{
while (head != nullptr)
{
Node * tmp = head->next;
delete head;
head = tmp;
}
}
BTW.: Please read some good books on how to implement lists.
BTW.2: Use some standard containers like vector or list if you really need it.

Finding the error in displaying the linked list

Assume we have a List class with a data member called front which is a Node pointer. Below is a member function to display the members of a list (the calling object).
It has an error. Identify and describe the error in a few
words. Then correct the error.
void display ()
{
Node *temp= new Node;
temp=front;
while (temp!=NULL)
{
cout<<temp->data<<"\t";
temp=temp->next;
}
}
This was one of the question in my test and I couldn't find anything wrong in the above given code. I even ran this code in the compiler and it works fine.
Can anyone tell where the error is?
Node *temp = new Node; // a pointer, called temp, allocated to a new block
//of memory of size Node
temp = front // the pointer to the block of memory was just overwritten, and now you
//don't have a pointer to the block of memory you just allocated
First, you don't need to call new here. Just declare the pointer and assign it at the same time.
Second, since you did call new, you've just created a memory leak, that is, you've allocated memory that now has no way of being deallocated (until the program shuts down).
Third, you should access front with an accessor method.
myList.GetFront() //this should return a pointer to the front of the list
Why? Well, what happens if you accidentally do something like:
front = front->next;
You've just lost the pointer to the front of your list, and so has every other method that uses front.

Will using "delete" here actually delete the object?

I was implementing a LinkedList using C++, and I seem to have forgotten a few things when dealing with dynamically allocated memory.
I have a node class:
class Node {
public:
Node(int d) {
data = d;
next = NULL;
}
Node(int d, Node* n) {
data = d;
next = n;
}
int data;
Node* next;
};
and in my LinkedList class, I have the following method:
void remove(int n) {
Node* current;
current = head;
Node* previous = NULL;
while ( current->data != n && current->next != NULL) {
previous = current;
current = current->next;
}
if (current->data == n) {
previous->next = current->next;
current->next = NULL;
delete current;
}
else {
std::cout << "Node not found" << std::endl;
}
}
I seem to have forgotten..When I do delete current does that delete the Node ? Like the actual object that the pointer current points to? Or does it just delete the pointer? Or does the deletion of a pointer pointing to dynamically allocated memory using delete delete both the pointer and the object? Or do I need to have defined a Node class destructor for that?
It just deletes the struct -in your case node- it points to, you can still use that pointer -make it point to another node-, in fact there's no way delete the pointer itself since it's allocated on the stack. it's automatically "deleted" when you leave the function.
p.s: no need to set current->next to null
Delete just free's the memory pointed to. This has the following implications:
You are not allowed to access the memory at this location (use after free)
The amount of memory you needed for your Node object is free, meaning your program would use less RAM.
The pointer itself points either to a non-valid location or NULL, if you follow best practise and set it to NULL manually.
The data at the memory location where your object was can be overwritten by any other task that has a valid pointer on this location. So technically the Node data still remains in memory as long as nobody else overwrites it.
delete p causes the object pointed to by p to cease to exist. This means that
1, If the object has a destructor, it is called; and
2. p becomes an invalid pointer, so that any attempt to dereference it is undefined behaviour.
Generally, the memory occupied by said object becomes available to the program again, though this is really an implementation detail.
The phrase "delete the pointer" is normally a sloppy shorthand for "delete the object pointed-to by the pointer".
Assuming that you have allocated your object using new delete on a pointer does the following:
calls the destructor of the object
request that the memory is free ( when that happens is actually implementation dependent )
At some point the memory manager will free and mark it as non-accessible by the process.
Thus it is up to you to set the pointer after calling delete to an agreed value. The best practice it to set it as nullptr for the latest compilers.
It does delete the actual structure pointed to by current. Pointers remain intact. No need for defining destructor.
The delete operator is to be applied to pointer to object. The pointer is an address of memory on heap allocated by calling new. Internally there is just table of addresses allocated by new. So the key to free such memory is just that address. In your case such address is stored in variable of type pointer to Node named current.
There are few problems in your code. The problematic one is that you have no posibility to tell whether node stored in current is actually allocated on heap. It might happen that current node is allocated on stack. E.g.
void someFunction(LinkedList &list) {
Node myLocalNode(10);
list.add(&myLocalNode);
list.remove(10); //<-- disaster happens here
}
The same applies to statically allocated global variables.
You must take care of extreme cases. Think about what happens when deleted object is the first one, pointed by variable head. By deleteing its memory you end up with dangling pointer in head, pointing to either unallocated memory or memory used by someone else.
My third objection is to writing such structure at all. I hope it is just some school excercise, because in any other cases you should (almost must) use some existing list like std::list from C++ STL.
Whenever you call delete on a pointer variable, the object to which it is pointing to gets deleted from the memory, however the 4 bytes allocated to the actual pointer variable (in your case, the current variable), the 4 bytes will be freed only when the variable will go out of scope, ie At the end of the function

Can I reuse a declared pointer if it's deleted?

In a linked list, I have the following code
Node *tmp = head;
Node *del = head->next;
tmp->next = del->next;
delete del;
del = tmp->next;
In my code, I deleted the pointer del first, later I point it to tmp->next. Will this work?
You don't actually delete the pointer variable itself, you just mark the memory area that it points to as free to use for future allocations (after calling the destructor but that's a different topic). The pointer variable just carries an address. Even after deletion the pointer variable is fine, but it points to an area in memory that has been freed, so its contents are undefined.
When the pointer variable is then reassigned to point to another memory address, it will have nothing to do with the old, "deleted" part of memory at all.