I came across this code:
void f(const std::string &s);
And then a call:
f( *((std::string*)NULL) );
A
Is using NULL references OK?
No, unless you do not like your boss and your job ;)
This is something VERY bad. One of most important point of reference that it can't be NULL (unless you force it)
You will sometimes see constructions like this in fairly esoteric template library code, but only inside a sizeof()
where it is harmless.
Supposing you wanted to know the size of the return type of a function-like type F
if it was passed a reference to a type T
as an argument (both of those being template parameters). You could write:
sizeof(F(T()))
But what if T happens to have no public default constructor? So you do this instead:
sizeof(F(*((T *)0)))
The expression passed to sizeof
never executes - it just gets analyzed to the point where the compiler knows the size of the result.
No. It is undefined behaviour and can lead to code to do anything (including reformatting you hard disk, core dumping or insulting your mother).
If you need to be able to pass NULL, then use pointers. Code that takes a reference can assume it refers to a valid object.
Addendum: The C++03 Standard (ISO/IEC 14882, 2nd edition 2003) says, in §8.3.2 "References", paragraph 4:
A reference shall be initialized to refer to a valid object or function. [Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer, which causes undefined behavior. As described in 9.6, a reference cannot be bound directly to a bit-field. ]
[Bold added for emphasis]
As others already said: A reference has to be valid. That's why it's a reference instead of a pointer.
If you want to make f() have a default behavior, you might want to use this:
static const std::string default_for_f;
void f(const std::string &s = default_for_f)
{
if (&s == &default_for_f)
{
// make default processing
}
else
...
}
...
void bar()
{
f(); // call with default behavior
f(default_for_f); // call with default behavior
f(std::string()); // call with other behavior
}
You can spare the default parameter for f(). (Some people hate default parameters.)
I'm curious - does function 'f' actually check for this condition? Because if it doesn't, and it tries to use the string, then this is clearly going to crash when you try to use it.
And if 'f' does check the reference for NULL, then why isn't it just using a pointer? Is there some hard and fast rule that you won't use pointers and some knucklehead obeyed the letter of the law without thinking about what it meant?
I'd just like to know...
f( *((std::string*)NULL) );
This is essentially dereferencing NULL, which on most systems is #defined to be 0. Last I checked 0x00000000 is an invalid memory address for doing anything.
Whatever happened to just checking
if (std::string.length() > 0) ....