At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.
There is a very good description of the differences here: http://www.dgp.toronto.edu/~patrick/csc418/wi2004/notes/PointersVsRef.pdf
The link given in the previous answer is a pretty good answer. But, it is easy to miss the point that there is in C++ both pointers and reference are ways of storing and working with actual memory addresses. They are the same thing. So... why have two different names, and two different syntaxes, for THE SAME THING? Well, pointers can be cast to have not type. That is, they can be treated as pointing to raw bytes of memory, and then you can to all sorts of mischief. Pointers do have types, but it is easy to make horrible mistakes with pointers and very difficult to find them. References are just easier to keep straight in your head and therefore less error prone. C++ uses strong typing to find all sorts of errors at compile time. And, also to enable a vast number of optimizations, that are only possible because of strong typing. So, the designers of C++ decided to add references in the hopes of weaning C programmers away from using pointers. It is one thing to know that the difference between pointers and references is only syntactic, and not semantic. It is another thing to understand why someone would add a syntactic alternative to a semantic feature that is already in a language.
Also keep in mind that references can normally be assumed to not be invalid (whereas pointers should always be checked for 0). There's only one *easy* way to get a dangling reference (returning a reference to a temporary) - other than that, you'd actually have to build some pretty contrived code to construct a dangling reference. Pointers still have their place, but I agree with stonewolf in many respects - references should today mostly replace passing pointers to objects as arguments to functions, for example.