This is all good advice, but do make sure that you get comfortable with raw pointers and manual memory management as well. There's all sorts of exciting trouble that you'll miss out on if you don't. (Seriously, though. These are core concepts, so get good with them.)
A pointer is a numeric value that is typically used to store a memory address. It's not the data. It just points to the data.
A pointer is just a number:
char* aPointer = (char*)100;
aPointer -= 50;
std::cout << "The number is " << (int)aPointer << "..." << std::endl;
//Note: Do not do this in production code or the skeleton man will eat you.
You can use a pointer to point to things on the stack:
int ary[] = {5, 6, 7};
int* aPointer = ary;
std::cout << "The array contains: " << std::endl;
std::cout << *aPointer << std::endl;
++aPointer;
std::cout << *aPointer << std::endl;
++aPointer;
std::cout << *aPointer << std::endl;
//Note: You can get fired for that too, unless you have a really good reason.
Or you can use it to point to dynamically allocated memory.
The thing to really grasp in that case is that new and delete are just functions with their own weird syntax. 'new' reserves a block of memory from the heap, and 'delete' releases a block that was previously reserved by 'new'. They're almost completely unrelated to the pointer or pointers that you use to keep track of that block during its lifetime.
One way to think of it is to think of memory as a set of pay lockers. 'new' puts a quarter in the slot (reserves the memory) and you write down the locker number (address) on a note-card (pointer). You can copy that number to another note-card or really do whatever you want with it. Just remember to return the locker key at the end of the day (delete).