Reading http://www.cprogramming.com/tutorial/references.html, it says:
In general, references should always be valid because you must always initi
You need to maintain sanity of your variables -- i.e., only pass a reference/pointer to some function if you know the function scope will not outlive you reference/pointer.
If you go and free some handle and then try to use said reference you will be reading free'd memory.
My question is how do I know that the object's memory hasn't been freed/deleted AFTER you've initialized the reference.
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.
What it comes down to is that I can't take this advice on faith and I need a better explanation
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.
There is no syntax to check whether reference is valid. You can test pointer for NULL, but there is no valid/invalid test for a reference. Of course, referenced object can be released or overwritten by some buggy code. The same situation is for pointers: if non-NULL pointer points to released object, you cannot test this.
You can't. You also can't with a pointer. Consider:
struct X
{
int * i;
void foo() { *i++; }
};
int main()
{
int *i = new int(5);
X x = { i };
delete i;
x.foo();
}
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.
C++ references are aliases. The effect of this is that dereferences to pointers don't necessarily happen where they appear, they happen where they are evaluated. Taking a reference to an object doesn't evaluate the object, it aliases it. Using the reference is what evaluates the object. C++ cannot guarantee references are valid; if it does, all C++ compilers are broken. The only way to do so is to eliminate all possiblity of dynamic allocation with references. In practice, the assumption is that a reference is a valid object. Since *NULL is undefined & invalid, it follows that for p = NULL, *p is also undefined. The problem with C++ is *p will be effectively passed to a function, or delayed in its evaluation until which time the reference is actually used. Arguing that it is undefined is not the point of the asker's question. If it were illegal, the compiler would enforce it, and so would the standard. Neither does, that I am aware of.
int &r = *j; // aliases *j, but does not evaluate j
if(r > 0) // evaluates r ==> *j, resulting in dereference (evaluate j) at this line, not what some expect
;
1) You can test a reference for aliasing a NULL pointer, &r is simply &(whatever r aliases to) (EDIT)
2) When passing a "dereferenced" pointer (*i) as a reference parameter, the dereference doesn't happen at the callsite, it may never happen, because it is a reference (references are aliases, not evaluations). That is the optimization of references. If they were evaluated at the callsite, either the compiler is inserting extra code, or it would be a call by value and less performant than a pointer.
Yes, the reference itself is not NULL, it is invalid, just as *NULL is invalid. It is the delaying of evaluation of dereference expressions that is not consistent with claiming it is impossible to have an invalid reference.
#include <iostream>
int fun(int & i) {
std::cerr << &i << "\n";
std::cerr << i << "\n"; // crash here
}
int main() {
int * i = new int();
i = 0;
fun(*i); // Why not crash here? Because the deref doesn't happen here, inconsistent, but critical for performance of references
}
EDIT: Changed my example as it has been misconstrued as suggestion for testing references, not what I wanted to demonstrate. I only wanted to demonstrate the invalid reference.