In the first example, num1 is a reference. A reference is an alias. So num and num1 refer to the exact same thing. Inside the compiler, num and num1 are just different names for the same thing. If you took the address of each, they would be equivalent.
assert(&num == &num1);
The second example creates a pointer, which is an entirely new variable with its own storage location. It stores the memory location of num. You can change num separately from num1; num can point to any integer variable. If you had a num2, you could say
num = &num2;
num now points to the location of num2 and knows nothing about num1. You cannot do that with the first one. num and num1 are inextricably linked. num = num2 would assign the value of num2 to num1 since num and num1 are just different names for the same thing.
In the first example, 4 bytes are allocated on the stack (for num). And num1 has no distinct storage. In the second, 8 bytes are allocated (assuming a 32-bit architecture).
int num1 = 5; //num1 is an int variable,has value 5,and a certain address in memory
int * ptr; // read right-to-left : create a pointer named ptr, pointing to ( * ) an integer
//ptr can hold adress of variables of type int
ptr=&num1; // take address of num1 using &,put this adress in ptr,now ptr points to num1
cout<<ptr; //if you open ptr and look what is in you will see an adress value e.g 0X123456
cout<<endl;
cout<<*ptr; // if you go to that adress and look what is in ( using * ) you will see value of 5.