Reading http://www.cprogramming.com/tutorial/references.html, it says:
In general, references should always be valid because you must always initialize a reference. This means that barring some bizarre circumstances (see below), you can be certain that using a reference is just like using a plain old non-reference variable. You don't need to check to make sure that a reference isn't pointing to NULL, and you won't get bitten by an uninitialized reference that you forgot to allocate memory for.
My question is how do I know that the object's memory hasn't been freed/deleted AFTER you've initialized the reference.
What it comes down to is that I can't take this advice on faith and I need a better explanation.
Can anyone shed some light?
I think it "depends". I know, that is not an answer, but it does really depend. I think coding defensively is a good practice to follow. Now if your stack track is 10 levels deep and any failure down the trace causes the entire operation to fail, then by all means, check at the top level and let any exceptions rise to the top. but if you can recover from someone passing you a null reference, the check where appropriate. In my experience, where I have to bring code together with other companies to integrate together, checking ( and logging ) everything at the public api level lets you deflect the finger pointing that happens when integration does not go as expected.
You can't. You also can't with a pointer. Consider:
Now, what code could you put in X::foo() to make sure that the i pointer is still valid?
Answer is that there is no standard check. There are some tricks that might work on msvc in debug mode (checking for 0xfeeefeee or whatever), but there's nothing that will consistently work.
If you need some sort of object that makes sure the pointer does not point at freed memory you'll need something much smarter than a reference or standard pointer.
This is why you need to be pretty darn careful with ownership semantics and lifetime management when working with pointers and references.
Because by the time you reach there you have made an undefined behavior for sure. Let me explain :)
Say you have:
Now, if you pass something like:
But if you do the following:
By the time you reach
fun
, you will be dereferencing *n which is undefined behavior if the pointer is deleted as in the example above. So, there is no way, and there must be now way actually because assuming valid parameters is the whole point of references.The short is that it could happen -- but if it does, you have a serious design problem. You also have no real way of detecting it. The answer is to design your program to prevent it from happening, not trying to build some sort of check that won't really work (because it can't).
First, there is never any way to detect if a memory location has been freed/deleted. That has nothing to do with whether or not it is null. The same is true for a pointer. Given a pointer, you have no way to ensure that it points to valid memory. You can test whether a pointer is null or not, but that's all. A non-null pointer may still point to freed memory. Or it may point to some garbage location.
As for references, the same applies in that you have no way of determining whether it references an object that is still valid. However, there is no such thing as a "null reference" in C++, so there is no need to check if a reference "is null".
Of course, it is possible to write code that creates what looks like a "null reference", and that code will compile. But it won't be correct. According to the C++ language standard, references to null can not be created. Attempting to do so is undefined behavior.
The better explanation is this: "a reference points to a valid object because you set it to point to a valid object". You don't have to take it on faith. You just have to look at the code where you created the reference. It either pointed to a valid object at that time, or it didn't. If it didn't, then the code is incorrect and should be changed.
And the reference is still valid because you know it is going to be used, so you have made sure not to invalidate the object it references.
It's really that simple. References stay valid as long as you don't destroy the object they point to. So don't destroy the object it points to until the reference is no longer needed.