A pointer can either point to a physical or virtual memory address, since you got virtual memory (normally reserved by your OS) and physical random access memory. The namespace of memory addresses however can be argued to always be virtual since it is only a key for the system to find a spot on the hardware. Another thing pointers can do for you is creating objects of a certain type. Example:
MyCustomClass* MyClass = new MyCustomClass();
this will create an object on the heap memory (and is also very easy to create a memory leak with :p). There are some other fun things pointer can do for you, like iterating through memory. Also pointer in cmparison to references are dynamic in their nature. While every datastructure in memory does have a memory address and therefore a static reference, pointers are dynamic in their nature. This means you can have n amounts of pointers, all pointing to the same address in memory. Also a pointer allows you to access a specific datastructure from anywhere in your code, without the need to move that object around. In general, this is what you will use pointers for most of the time, to avoid shifting around big chunks of data. By simply passing a memory address you save resources. Pointers can also be used to not only reference and create data, but also to free up memory again. You can manually decide when you don’t need a referenced object anymore and delete it using the pointer.
That said, with great power comes great responsibility. Therefore pointers should be used with caution, especially when they are your only access to an object. If your pointer goes out of scope or does not point to it’s initial location you might create a memory leak. This memory will not get freed up again and will be permanently blocked during the runtime of your program. An exampl might be somethig like that:
void DoStupidStuff()
{
GiganticObj* MyObj = new GiganticObj();
}
This will lead to a memory leak. Also, rule of thumb is to use the static reference of an object rather than a pointer if possible. And to not use pointer for datastructures that are <= 4 byte. If you are working with C++ chances are that you are forbidden to use raw pointers in the first place and are obligated to use smart pointers, which are simply wrappers for raw pointers making them safer, since they destroy an object as soon as it goes out of scope. Mhhh, I’m sure there is more but these are the things I normally encounter…