They are a basic part of the C language. Without being rude, I think the key thing to consider is that they are not something to be avoided. They are another tool at your disposal, and a powerful one at that.
In general, they are used when you want to access large amounts of data (ie: arrays, massive structures, dynamic memory allocation, etc). They are also very useful when designing APIs (application programming interfaces). This shouldn't really be C# question, as in C# and C++, you can pass by value or by reference, and the nature of your question changes based on the usefulness of passing by value or reference, along with the user of other means of accessing data external to a function, class, etc.
Pass by Reference / Value in C++
If you can just pass by value, and the value is read-only, you're fine without a pointer, as you have no means to change the value. A common case is a simple sum function:
int sum (int a, int b) {
int value = a + b;
return value;
}
You have no need to modify the values provided, and you're only accessing simple values, rather than arrays or complex structures.
Now, if you're modifying the contents of a large array, especially if the size of the array can change at run time (ie: linked lists and other data structures) you need pointers, period. If you're modifying multiple values, you could either use pointers, or you could just use the return value of a function (ie: int mysum = sum(1,2);
). About the only concern I encounter when using pointers in regular work is making sure any possible NULL pointer values are checked for at the beginning of each function. The real problem is when working with larger projects where you can get non-NULL, invalid/corrupt pointers from a poorly written third party API or library. That's where the real fun begins, debugging with JTAG debuggers, GDB, etc.