In C and C++, pointers are inherently unsafe, that is, when you dereference a pointer, it is your own responsibility to make sure it points somewhere valid; this is part of what "manual memory management" is about (as opposed to the automatic memory management schemes implemented in languages like Java, PHP, or the .NET runtime, which won't allow you to create invalid references without considerable effort).
A common solution that catches many errors is to set all pointers that don't point to anything as NULL (or, in correct C++, 0), and checking for that before accessing the pointer. Specifically, it is common practice to initialize all pointers to NULL (unless you already have something to point them at when you declare them), and set them to NULL when you delete or free() them (unless they go out of scope immediately after that). Example (in C, but also valid C++):
void fill_foo(int* foo) {
*foo = 23; // this will crash and burn if foo is NULL
}
A better version:
void fill_foo(int* foo) {
if (!foo) { // this is the NULL check
printf("This is wrong\n");
return;
}
*foo = 23;
}
Without the null check, passing a NULL pointer into this function will cause a segfault, and there is nothing you can do - the OS will simply kill your process and maybe core-dump or pop up a crash report dialog. With the null check in place, you can perform proper error handling and recover gracefully - correct the problem yourself, abort the current operation, write a log entry, notify the user, whatever is appropriate.
Answer from tdammers on Stack ExchangeIn C and C++, pointers are inherently unsafe, that is, when you dereference a pointer, it is your own responsibility to make sure it points somewhere valid; this is part of what "manual memory management" is about (as opposed to the automatic memory management schemes implemented in languages like Java, PHP, or the .NET runtime, which won't allow you to create invalid references without considerable effort).
A common solution that catches many errors is to set all pointers that don't point to anything as NULL (or, in correct C++, 0), and checking for that before accessing the pointer. Specifically, it is common practice to initialize all pointers to NULL (unless you already have something to point them at when you declare them), and set them to NULL when you delete or free() them (unless they go out of scope immediately after that). Example (in C, but also valid C++):
void fill_foo(int* foo) {
*foo = 23; // this will crash and burn if foo is NULL
}
A better version:
void fill_foo(int* foo) {
if (!foo) { // this is the NULL check
printf("This is wrong\n");
return;
}
*foo = 23;
}
Without the null check, passing a NULL pointer into this function will cause a segfault, and there is nothing you can do - the OS will simply kill your process and maybe core-dump or pop up a crash report dialog. With the null check in place, you can perform proper error handling and recover gracefully - correct the problem yourself, abort the current operation, write a log entry, notify the user, whatever is appropriate.
The other answers pretty much covered your exact question. A null check is made to be sure that the pointer you received actually points to a valid instance of a type (objects, primitives, etc).
I'm going to add my own piece of advice here, though. Avoid null checks. :) Null checks (and other forms of Defensive Programming) clutter code up, and actually make it more error prone than other error-handling techniques.
My favorite technique when it comes to object pointers is to use the Null Object pattern. That means returning a (pointer - or even better, reference to an) empty array or list instead of null, or returning an empty string ("") instead of null, or even the string "0" (or something equivalent to "nothing" in the context) where you expect it to be parsed to an integer.
As a bonus, here's a little something you might not have known about the null pointer, which was (first formally) implemented by C.A.R. Hoare for the Algol W language in 1965.
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.
Because a reference carries the semantic that it points to a valid memory address that never changes; i.e. that dereferencing it is safe/defined and so no NULL checks are required. References cannot be reassigned by design.
You use a pointer when the var can be NULL and client code has to handle that case. You use a reference when you can guarantee a valid/initialised memory address.
One example of using pointers is as a member of a class to store a "reference" to some instance that might not be known or able to be initialised at class construction time. However, member references must be initialised at construction time (via initialiser lists) and their assignment cannot be deferred.
If you allow a null reference it is then no different to a pointer besides syntax (the same NULL checks would need to take place.)
Update:
"And, in most OOP languages, objects can be NULL - Pascal, C#, Java, JavaScript, PHP, etc. [...] So why is C++ somehow special and doesn't have a NULL object? Was it just an overlook or an actual decision?"
I think you are a bit confused about this. Java and C# etc. might give the impression of "NULL objects", but these object references are more or less like a C++ pointer with simpler syntax, GC instrumentation and exception throwing. In those languages if you operate on a "Null Object" you will get some kind of exception like NullReferenceException (C#). Hell, in Java its called a NullPointerException.
You have to check for null before you can use them safely. Kind of like C++ pointers (except in most managed languages, pointers are initialised to NULL by default, whereas in C++ its usually up to you to take care of setting the initial pointer value (otherwise undefined/whatever memory was already there)).
The C++ view is about having choice, and hence being verbose:
- Use a plain pointer to do how you please, checking NULL where necessary.
- Use references which have a compiler-enforced validity semantic/constraint.
- Roll your own smart pointers that do bookkeeping and behave whichever way you want them to.
- Using void pointers (cautiously!) to reference an untyped block of memory if ever required.
Please have a look at differences between pointers and references - while the standard leaves it open how references are implemented, they are at the moment always implemented as pointers.
Which means that the main difference between them is a) semantics b) pointers can be reseated c) pointers can be null.
So the short answer is, this was done on purpose. When you as programmer see a reference you should know that a) that reference is populated b) it won't change (and c) you can use it with the same semantics as an object).
Would the standard allow a null reference, you would always have to check for null before using a reference, which was not wanted.
Edit:
Regarding your edit, I guess the confusion here might stem from the fact that most simpler OO languages hide what is going on. To take Java as example, while it looks like you have NULL objects, and can assign them, you really can't - what is really going on is that Java only has pointers, and can assign null values to those pointers. Since it is impossible to actually have objects directly in Java, they do away with pointer semantics and treat the pointer as the object. C++ is simply more powerful - and error prone (Java enthusiast would say that stack user class instances are not required, and the decision to not have them in Java was driven to reduce complexity, and make Java easier to use). It also follows that, since Java doesn't have objects, it doesn't have references. What really doesn't help, though, is that Java calls what a C++ person would call a pass-by-value of a pointer a pass-by-reference.
In C and C++, pointers are inherently unsafe, that is, when you dereference a pointer, it is your own responsibility to make sure it points somewhere valid; this is part of what "manual memory management" is about (as opposed to the automatic memory management schemes implemented in languages like Java, PHP, or the .NET runtime, which won't allow you to create invalid references without considerable effort).
A common solution that catches many errors is to set all pointers that don't point to anything as NULL (or, in correct C++, 0), and checking for that before accessing the pointer. Specifically, it is common practice to initialize all pointers to NULL (unless you already have something to point them at when you declare them), and set them to NULL when you delete or free() them (unless they go out of scope immediately after that). Example (in C, but also valid C++):
void fill_foo(int* foo) {
*foo = 23; // this will crash and burn if foo is NULL
}
A better version:
void fill_foo(int* foo) {
if (!foo) { // this is the NULL check
printf("This is wrong\n");
return;
}
*foo = 23;
}
Without the null check, passing a NULL pointer into this function will cause a segfault, and there is nothing you can do - the OS will simply kill your process and maybe core-dump or pop up a crash report dialog. With the null check in place, you can perform proper error handling and recover gracefully - correct the problem yourself, abort the current operation, write a log entry, notify the user, whatever is appropriate.
Answer from tdammers on Stack ExchangeReferences are not pointers.
8.3.2/1:
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. ]
1.9/4:
Certain other operations are described in this International Standard as undefined (for example, the effect of dereferencing the null pointer)
As Johannes says in a deleted answer, there's some doubt whether "dereferencing a null pointer" should be categorically stated to be undefined behavior. But this isn't one of the cases that raise doubts, since a null pointer certainly does not point to a "valid object or function", and there is no desire within the standards committee to introduce null references.
The answer depends on your view point:
If you judge by the C++ standard, you cannot get a null reference because you get undefined behavior first. After that first incidence of undefined behavior, the standard allows anything to happen. So, if you write *(int*)0, you already have undefined behavior as you are, from a language standard point of view, dereferencing a null pointer. The rest of the program is irrelevant, once this expression is executed, you are out of the game.
However, in practice, null references can easily be created from null pointers, and you won't notice until you actually try to access the value behind the null reference. Your example may be a bit too simple, as any good optimizing compiler will see the undefined behavior, and simply optimize away anything that depends on it (the null reference won't even be created, it will be optimized away).
Yet, that optimizing away depends on the compiler to prove the undefined behavior, which may not be possible to do. Consider this simple function inside a file converter.cpp:
int& toReference(int* pointer) {
return *pointer;
}
When the compiler sees this function, it does not know whether the pointer is a null pointer or not. So it just generates code that turns any pointer into the corresponding reference. (Btw: This is a noop since pointers and references are the exact same beast in assembler.) Now, if you have another file user.cpp with the code
#include "converter.h"
void foo() {
int& nullRef = toReference(nullptr);
cout << nullRef; //crash happens here
}
the compiler does not know that toReference() will dereference the passed pointer, and assume that it returns a valid reference, which will happen to be a null reference in practice. The call succeeds, but when you try to use the reference, the program crashes. Hopefully. The standard allows for anything to happen, including the appearance of pink elephants.
You may ask why this is relevant, after all, the undefined behavior was already triggered inside toReference(). The answer is debugging: Null references may propagate and proliferate just as null pointers do. If you are not aware that null references can exist, and learn to avoid creating them, you may spend quite some time trying to figure out why your member function seems to crash when it's just trying to read a plain old int member (answer: the instance in the call of the member was a null reference, so this is a null pointer, and your member is computed to be located as address 8).
So how about checking for null references? You gave the line
if( & nullReference == 0 ) // null reference
in your question. Well, that won't work: According to the standard, you have undefined behavior if you dereference a null pointer, and you cannot create a null reference without dereferencing a null pointer, so null references exist only inside the realm of undefined behavior. Since your compiler may assume that you are not triggering undefined behavior, it can assume that there is no such thing as a null reference (even though it will readily emit code that generates null references!). As such, it sees the if() condition, concludes that it cannot be true, and just throw away the entire if() statement. With the introduction of link time optimizations, it has become plain impossible to check for null references in a robust way.
TL;DR:
Null references are somewhat of a ghastly existence:
Their existence seems impossible (= by the standard),
but they exist (= by the generated machine code),
but you cannot see them if they exist (= your attempts will be optimized away),
but they may kill you unaware anyway (= your program crashes at weird points, or worse).
Your only hope is that they don't exist (= write your program to not create them).
I do hope that will not come to haunt you!
You cannot do this during references, as they should never be NULL. There are basically three options, one using a pointer, the others using value semantics.
With a pointer (note: this requires that the resource doesn't get destructed while the caller has a pointer to it; also make sure the caller knows it doesn't need to delete the object):
SomeResource* SomeClass::getSomething(std::string name) { std::map<std::string, SomeResource>::iterator it = content_.find(name); if (it != content_.end()) return &(*it); return NULL; }Using
std::pairwith aboolto indicate if the item is valid or not (note: requires that SomeResource has an appropriate default constructor and is not expensive to construct):std::pair<SomeResource, bool> SomeClass::getSomething(std::string name) { std::map<std::string, SomeResource>::iterator it = content_.find(name); if (it != content_.end()) return std::make_pair(*it, true); return std::make_pair(SomeResource(), false); }Using
boost::optional:boost::optional<SomeResource> SomeClass::getSomething(std::string name) { std::map<std::string, SomeResource>::iterator it = content_.find(name); if (it != content_.end()) return *it; return boost::optional<SomeResource>(); }
If you want value semantics and have the ability to use Boost, I'd recommend option three. The primary advantage of boost::optional over std::pair is that an unitialized boost::optional value doesn't construct the type its encapsulating. This means it works for types that have no default constructor and saves time/memory for types with a non-trivial default constructor.
I also modified your example so you're not searching the map twice (by reusing the iterator).
Why "besides using pointers"? Using pointers is the way you do it in C++. Unless you define some "optional" type which has something like the isNull() function you mentioned. (or use an existing one, like boost::optional)
References are designed, and guaranteed, to never be null. Asking "so how do I make them null" is nonsensical. You use pointers when you need a "nullable reference".
I just have to get this rant off my chest, since I've received a few comments about it on both my blog and an associated Reddit post.
Maybe I'm preaching to the choir. Maybe I'm feeding trolls. I'll assume that there are those out there who, in good faith, really don't understand that C++ references are not nullable.
Many other languages made the fatal error of permitting null as valid for all reference types, where every non-builtin is a reference type and they have boxing around classes. Here's some psuedo-Java:
class MyType {
public void foo() {}
};
void my_fun(MyType instance) {
instance.foo(); // <-- MAY THROW
}
void another_fun() {
my_fun(null); // <-- explodes
}This is semantically similar to the following C++:
class MyType {
public:
void foo() {}
}
void my_fun(MyType* instance) {
__check_nonnull(instance); // <-- Check inserted by compiler
instance->foo();
}
void another_fun() {
my_fun(nullptr);
}
With implicitly nullable references, every single use of the reference is a candidate for a nullptr.
On the contrary, C++ affords the guarantee that a T& always refers to a valid T.
Of course, all of C++'s guarantees have a caveat: Every guarantee goes out the window if any part of a program contains undefined behavior.
Here's a common "C++ null reference" example that detractors provide:
class MyClass {
public:
void foo();
};
void do_thing(MyClass& inst) {
inst.foo();
}
void other_thing() {
MyClass* inst_ptr = nullptr;
do_thing(*inst_ptr);
}
Of course, the fact that we dereference inst_ptr means the program behavior is undefined. The call inst.foo() is perfectly legal, and checking that &inst != nullptr is unnecessary.
In fact, the very expression &<anything> != nullptr is completely non-sensical. C++ guarantees that the builtin address-of operator& never returns nullptr. We even get a warning about it from GCC.
Saying "impossible thing might happen" is not useful. Imagine this code:
class MyClass {
public:
void foo();
};
class UnrelatedClass {
public:
void foo();
}
void do_thing(MyClass& inst) {
inst.foo();
}
Saying "inst might be a null reference" is equivalent to saying "inst might actually be an UnrelatedClass" because someone might do this:
void garbage_fn() {
UnrelatedClass garbage;
do_thing(reinterpret_cast<MyClass&>(garbage));
}Both cases are undefined, but for some reason, people still believe that null-references are a thing.
Edit: Wording
Edit to clarify:
I'm not saying that dereferencing null pointers never occurs in practice. What I'm really saying is that there is no use in worrying if a client has dereferenced a null pointer in order to fulfill a reference parameter on your API. There's no meaningful action that you can take.
Just like this is never null. In fact, GCC will remove checks for null this because it can never be null.
The important point here is that you should never, ever, ever, ever check if a reference (or this) has the value of the null pointer. What could you possibly do that would be correct in that case? If you get to the point where a reference has the value of the null pointer your program is already borked. You can't fix it. Knowing how to fix it would imply that you knew about the bug somewhere else in your program that allowed the reference to contain the value of the null pointer. If you did know what that bug was you would simply fix that bug.