The output is the same because they are both doing the same thing. Pointers are exactly what they sound like: They point to objects. The '->' operator is called the 'follow-through' operator, and basically, it follows-through to what the pointer points to, and allows you to operate on it.
There are some cases where the only way to do something is with a pointer. If you can do it without a pointer though, you should avoid using pointers. If you have to use pointers, at least use smart pointer classes that make it hard for you to mess it up.
The problem with pointers is that while they are powerful, they are also way too easy to get wrong, which is why you should avoid them when you don't have to use them.
Like LB said, they can be very powerful, and allow for immense speed gains if you know what you are doing, but in cases that are not speed sensitive- avoid them.
But they can be a massive headache when you do use them.
If someone is mauled by a animal, that person learns to respect the animal. Get the idea? Pointers: learn, respect and embrace them, but don't avoid them for pointers are a critical fundamental concept of computers.
People have the tendency to say that pointers lead to "messy", "buggy" and "unsafe" code, but I find that people who suggest such things tend to be either incompetent or prefer to be as far away from the hardware as possible; usually the ones who believe type-casting is "ugly".
@Framework if you can remember exactly how to handle all pointers in a large program, then fine. The rest of us will have to remain with our smaller brains doing things the more abstracted way to make it harder to mess up.
In many cases avoiding pointers allows the compiler to better optimize code.
Oh, and casting isn't ugly, it's just a code smell.
"In many cases avoiding pointers allows the compiler to better optimize code."
Not true. References don't exist in assembly. If the compiler replaces the referent with an address, then sure, your code will be a little bit faster, but if the reference is implemented with a pointer, there's likely no gain in performance.
Note: I never used the word "reference" in that sentence.
The problem is that pointers can take any arbitrary value, making it hard for the compiler to guarantee it only taking certain values. With more abstracted approaches, it is very easy for the compiler to be sure that it can use an optimization.
The implementation doesn't matter when the compiler knows that it can only follow a certain interface and behavior. With just raw pointers it's much harder to tell, but when you get specific and use a mart pointer, reference wrapper, or std::function, it enables the compiler to optimize the code from a more abstract viewpoint where there are more restrictions that give the compiler more wiggle room. You can't honestly tell me that with optimizations enabled the compiler won't try to take advantage of the fact that you can't do something.
The compiler can see everything a pointer does. If a compiler sees that a pointer only points to some address, the compiler can optimise the pointer by keeping the pointer in a register and maybe the address pointed to by the pointer. Also, if the compiler sees that a pointer changes address frequently, it can allocate a register for it and keep it there.
"You can't honestly tell me that with optimizations enabled the compiler won't try to take advantage of the fact that you can't do something."
The compiler can do the same with naked pointers. If the compiler sees that a pointer doesn't do X, it can optimise the pointer by performing optimisation Y. Besides, abstraction has intrinsic overheads that hinder performance; while not a significant performance hit, it's still matters in speed-essential environments such as hard real-time systems.
@Major Tom: copying a pointer does not have the same effect as copying a class, and you cannot compare the two. What I am referring to is that with pointers you have to continuously dereference the pointer to access the data it points to, and this operation takes time.
@Framework: The compiler cannot, especially with PIMPL. Maybe the linker can, but it's better to optimize sooner than later.
I am definitely willing to say I am wrong, but this is the way I see it: a raw pointer is like a class with get_health() and set_health() - the health could be manipulated in any way at any time from anywhere. However, if you instead change the interface by replacing get_health() with draw_to_screen() and set_health() with a damage&healing system, the compiler can more obviously tell that the health can only change in certain ways, not just arbitrarily.
At least, I always thought it was easier to defend yourself if you knew you would only have attacks coming from your front than if you had no idea where attacks might come from.