Pointers are normal variables, which content is a memory address. This memory can be heap memory or stack memory. Don't confuse the pointer with the memory space it points to.
Your first code allocates space on the heap which can hold an int. You store a pointer to that memory on the stack.
Your second code allocates space on the stack which can hold an int. You store a pointer to that memory on the stack.
So both pointers are on the stack, but only the second points to the stack.
In both cases, the type you allocate is a primitive type. Primitive types aren't initialized per default, unless you immediately assign a value to it (your second code), or use the constructor syntax, which also works with heap-allocated values:
int *max = new int(0);
The same syntax can be used in your second code, by the way:
int myVar(20);
In case you're interested: You can also define pointers on the heap. int*
is the type of pointers to int
s, so just go ahead and allocate such a type on the heap:
new int*();
This expression returns an int**
, which you can then store somewhere. Again, you typically store this pointer-to-pointer on the stack:
int **pointerToPointer = new int*();
As with int
s, you can initialize an int*
in the new-expression to some pointer-to-int (here, the max
pointer from above):
int **pointerToPointer = new int*(max);
Now you have two pointers with the same address: max
(pointer on the stack) and some pointer on the heap which you point to using pointerToPointer
, i.e. the following holds (I dereference `pointerToPointer, which leads to the value stored behind this pointer, which is a pointer to an int):
max == *pointerToPointer