In the first case the modification of head inside the loop does not modify what head points to outside the loop. In the second case, when the function exits you will actually have modified what the pointer used as argument points to.
Run the following and you will see that at "THIRD *p" you will have changed p in main to point to global2.
Code:
#include <iostream>
int global1 = 10, global2 = 20;
void printLL(int* p) {
std::cout << "Pointer: " << *p << std::endl;
p = &global2; // This has no effect
}
// compare to
void printLL2(int*& p) {
std::cout << "Reference to pointer: " << *p << std::endl;
p = &global2; // p in main will now continue to point to global2
}
int main()
{
std::cout << "global1: " << global1 << std::endl;
std::cout << "global2: " << global2 << std::endl;
int *p = &global1;
std::cout << "FIRST *p: " << *p << std::endl;
printLL(p);
std::cout << "SECOND *p: " << *p << std::endl;
printLL2(p);
std::cout << "THIRD *p: " << *p << std::endl;
}