Reputation: 440
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>
Upvotes: 3
Views: 1691
Reputation: 19
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:
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;
}
Upvotes: 2
Reputation: 33932
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.
Upvotes: 0
Reputation: 12174
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
Upvotes: 1
Reputation: 371
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];
}
Upvotes: 0