I've mostly only worked with C and am running into some unfamiliar issues in C++.
Let's say that I have some function like this in C, which would be very typical:
int some_c_function(const char* var)
{
if (var == NULL) {
/* Exit early so we don't dereference a null pointer */
}
/* The rest of the code */
}
And let's say that I'm trying to write a similar function in C++:
int some_cpp_function(const some_object& str)
{
if (str == NULL) // This doesn't compile, probably because some_object doesn't overload the == operator
if (&str == NULL) // This compiles, but it doesn't work, and does this even mean anything?
}
Basically, all I'm trying to do is to prevent the program from crashing when some_cpp_function() is called with NULL.
What is the most typical/common way of doing this with an object C++ (that doesn't involve overloading the
==
operator)?Is this even the right approach? That is, should I not write functions that take an object as an argument, but rather, write member functions? (but even if so, please answer the original question)
Between a function that takes a reference to an object, or a function that takes a C-style pointer to an object, are there reasons to choose one over the other?
You can use a special designated object as the null object in case of references as follows:
No, references cannot be null (unless Undefined Behavior has already happened, in which case all bets are already off). Whether you should write a method or non-method depends on other factors.
If you need to represent "no object", then pass a pointer to the function, and let that pointer be NULL:
If "no object" never needs to be represented, then references work fine. In fact, operator overloads are much simpler because they take overloads.
You can use something like boost::optional.
You should use NULL only with pointers. Your function accepts a reference and they can't be NULL.
Write your function just like you would write it in C.
A C++ reference is not a pointer nor a Java/C# style reference and cannot be NULL. They behave as if they were an alias to another existing object.
In some cases, if there are bugs in your code, you might get a reference into an already dead or non-existent object, but the best thing you can do is hope that the program dies soon enough to be able to debug what happened and why your program got corrupted.
That is, I have seen code checking for 'null references' doing something like:
if ( &reference == 0 )
, but the standard is clear that there cannot be null references in a well-formed program. If a reference is bound to a null object the program is ill-formed and should be corrected. If you need optional values, use pointers (or some higher level construct likeboost::optional
), not references.As everyone said, references can't be null. That is because, a reference refers to an object. In your code:
you are taking the address of the object
str
. By definition,str
exists, so it has an address. So, it cannot beNULL
. So, syntactically, the above is correct, but logically, theif
condition is always going to be false.About your questions: it depends upon what you want to do. Do you want the function to be able to modify the argument? If yes, pass a reference. If not, don't (or pass reference to
const
). See this C++ FAQ for some good details.In general, in C++, passing by reference is preferred by most people over passing a pointer. One of the reasons is exactly what you discovered: a reference can't be
NULL
, thus avoiding you the headache of checking for it in the function.C++ references naturally can't be null, you don't need the check. The function can only be called by passing a reference to an existing object.