Vead, as you're aware, a variable is a name given to a place to store a value.
That name is only important to you. When the program is compiled, that name essentially disappears, and the program works with the storage location.
There are multiple types of "locations", but let's keep it very simple and limit ourselves to addressable memory as the type of "location", and let's also imagine that it is linearly addressable from zero to some arbitrary maximum value.
When you define a variable (say "int i;") the compiler will pick a location for it. That location is fixed (or at a fixed offset from something) and the compiler can associate a literal to be used for it's address. Let's say the compiler chose 3.
Whenever the program needs to address i, it will get it from location 3. Each time it wants i, you will see it literally asking for location 3. That 3 is essentially a pointer to a memory location, but because it never changes, the compiler can do the work of telling the program exactly where to look to find what you called i.
After the program is compiled, if you had some reason to want to move i from location 3 to location 4 (and you would probably never want to do this, it's just a thought experiment) you would have to go through the program looking for each place it refers to location 3 in memory and change it to 4.
Let's now assume that we define our variable as "int *i". Surprisingly, very little has changed. i might still be assigned the memory location 3, and references to it will still all be looking for location 3, HOWEVER location 3 is not the location of the integer value, it is now the place where the location of the integer value is stored. Now, whenever we want the integer value (by referring to *i) the compiler will first do almost exactly what it did before, it will get the value stored in location 3, but instead of this being the integer value, it needs to do the additional step of retrieving the value from the location stored in location 3. Let's imagine that this is currently 12. It now must get the value from location 12.
So, i, which is represented by a fixed location in memory, now contains a reference to another location. Referring to i will return that reference, using *I will cause the compiler to get the reference, then get the location pointed to by that reference -- the integer value. Because there variable stores a reference, seeing through the reference to the value it points to is called dereferencing, because you no longer get the reference.
Incidentally, I also glossed over how the location 12 became the place to store the integer value.
With pointers, you need you perform an additional step to give them a location to point to. In your example, you used one of the easiest, the location of something else. However you most often (although it is frequently hidden) request that the operating system allocate you some memory it can guarantee that nobody else is legitimately currently using. What it will return is the address of a location. In my example above, it presumably returned the value 12. When I store 12 into i, I can then dereference i to get the value stored in location 12.
In C++ you may end up using explicit pointers far less than you would have in C. However it is still vital (maybe even more vital) to understand them, because the management of memory is underpinned by your careful and considered use of pointers, and pointer-like structures.
For simple examples like mine above, if you allocate a single memory location to a single variable once in your program and fail to free it after you're finished, not much harm will arise. However, if you do that each time a routine is called, and it is called frequently, you will start to consume (or worse, fragment) memory, and eventually your program may crash as it runs out of memory.
Remember that 12 I said the operating system told you was there location you could use? Well, you need to tell the operating system to free up that block of memory when your finished. In order to do that, you return that value to the operating system, and it can use it to look it up and mark it as available for use one again. If your program has lost this value (perhaps by accidentally overwriting i) then it can never be freed.
An interesting analogy is to consider allocated memory as a helium balloon. When you ask for some memory, the operating system blows up an appropriately sized balloon and hands you the string. In this model, pulling in the string to get the balloon is dereferencing. When you're finished you hand back the string and the OS deflates it again. If you let go of the string, the balloon is still there, but it can never be deflated. If there are too many of these balloons taking up room, soon enough the OS won't have enough space to blow up another balloon.
As you learn more about pointers, you'll realise the real power is not in single variables, but pointers to structures that themselves contain other pointers. This is like pulling on a string to get the balloon, and finding that the balloon is connected to more strings, which are connected to balloons with even more strings, and so on. You might only be holding a single string, but through it, you have access to hundreds of balloons floating above you.
And, you also need to understand that you can tie as many strings of your own to a balloon (multiple pointers can point to the same memory location), but that it is important to only hand one of them back to the OS, to only hand back those you've been given, and not to pull on a string once you've passed it back -- free memory once only, only attempt to free memory that has been allocated (and use the matching method), and don't dereference pointers that are not valid.
An understanding of pointers will allow you to understand things as simple as methods of parameter passing, up to the complexities of objects.
Once you think you understand pointers, someone will mention reference counting, and maybe even the horrors of garbage collection, but you're probably safe from having to think about those for a while (actually, these are both ways of "simplifying" the use of pointers. That's all fine until you're in an environment that uses a combination of these)