so when you're converting a pointer to a reference, you've got to do error checking one way or another.
That is only true if you're converting an invalid pointer to a reference and that is bad. The other way around is always right if you don't do this.
So in fact the right way is to put assertions all around pointers usage (getting pointer value, passing it around etc) to make sure it's valid. THEN when you're using references, you don't need to check again, because you assume that your code that have been using pointers was checked.
As you used pointers only where they were necessary, you sudently don't have to check them everywhere in your project, only where necessary (in low level and generic code most of the time).
In other parts of the code, you're passing references or anything else that is suitable, sometimes pointers but only when you need them to be null sometimes. As thay can be null in those parts of the code, your code will naturally take acount of null because it's normal behaviour (like when you return a pointer from a "find" function that could return nothing but life continues if it does).
Then, you start to understand that when you use pointers and references, with and without constness, you, in fact, setup some kind of protocol.
The idea is that when you ask for (non-const) references as function parameter, you suggest that you will modify the given object but it have to exist.
When it's a const reference, you say that you'll just read informations from it but not change it's state in any way (other than mutable state...) but still it have to be an object that exist.
When it's a pointer as parametter, you suggest that, well maybe you'll provide some informations to process, but if you don't (nullptr) it's still fine to execute the function.
When you're returning a const reference from a function, you say that you can read the object but don't touch it!
When you're returning a reference from a function you say that you allow the user to manipulate the object and you suggest (because you write valid code, right?) that the lifetime of the object will be at least as long as the lifetime of the owner of the function (member or not).
If you return a pointer, you suggest that you may, or not, return a result but it's facultative and it's not an error.
So, the practice of reducing use of pointers to where it's necessary will modify how you think and organize your code from bottom layer to top layer, making code easier to manipulate the higher you get.
Sure but aren't pointers implemented the same way? When you say "the compiler remembers" you mean it stores it in a processor register, which is how pointers are typically done.
Just. Forget. About. Reference. Implementation.
As already said, they can be implemented in memory "like" pointers but they are not adn it's not always the case are nothing in the standard say how they should be implemented.
There is no other guarantee about references than they are just nicknames for objects and that they should then never be uninitialized (if your code is correct).
It's specified that dereferencing a null pointer or a pointer pointing to unallocated memory is undefined behaviour. So you should never get to this point. If you do, then you didn't hear the alarm ringing when you started to cast things around too much.
Back to your example, I would have put checking in the two functions each time I assign a value to a pointer. That's the pointer the source of the problem, not the reference.
Again, there is smart pointers too that help having null pointers without manipulating pointers, but we didn't talk a lot about it here. I agree with Average Software about the alarming count of C++ programmers that prefer allowing mistakes instead of eliminating them where possible.
I almost always use const references rather than passing by value. Do you have some kind of argument why passing by value is better?
If you're using native types as parametters it's better to use value than reference (if it's const).
In function returns you'd better return a local object by value (if possible) than by reference as it's life is limited by the scope of the called function. For example you have to return a std::vector by value in a "search" function. But then don't worry much about performance : there is standardized optimizations that occurs most of the time, named NRVO (
http://msdn.microsoft.com/en-us/library/ms364057(VS.80).aspx for example, buyt it's valid for all recent compiler).
(c++ is really a lot of things to keep in mind together to code well... by the way, you should really read this :
http://www.tantalon.com/pete/cppopt/main.htm )