NULL for C
In C, we use NULL to represent NULL pointers, which means we can write the following code:
int *i = NULL;
foo_t *f = NULL;
In fact, in the C language, NULL is usually defined as follows:
#define NULL ((void *) 0)
That is, NULL is actually a void * pointer, and then the void * pointer is implicitly converted to the corresponding type when assigned to the pointer of int * and foo_t *. In the case of a C + + compiler to compile the error, because C + + is strongly typed, void * is not implicitly convertible to other pointer types, so typically, the compiler provides a header file that defines null:
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *) 0)
#endif
0 of C + +
Because C + + cannot implicitly convert a pointer of type void * to another pointer type, and in order to solve the problem of NULL pointers, the introduction of a null pointer in C + + means that there is a code similar to the above to define null. In fact, C + + 's book would suggest that C + + is more accustomed to using the null pointer instead of NULL, although NULL is 0 under the C + + compiler. Why do C + + books recommend using 0 instead of NULL to represent NULL pointers? Let's look at an example:
A function is declared in the Foo.h file:
void Bar (Sometype1 A, sometype2 *b);
This function is called in A.cpp, B.cpp, respectively:
A.cpp:
Bar (A, b);
B.cpp:
Bar (A, 0);
All right, these codes are normal, perfect compilation runs. But suddenly at some point we expanded our function, we needed to extend the bar function, we used overloads, and now the Foo.h declaration is as follows:
void Bar (Sometype1 A, sometype2 *b);
void Bar (Sometype1 A, int i);
This is a dangerous time, and the calling code in A.cpp and B.cpp is not going to work as expected at this time. But we'll soon find out that 0 in B.cpp is an integer, that is, when overload resolution, we know that it calls the overloaded function of void bar (Sometype1 A, int i), so we can make the following modifications to let the code run as expected:
Bar (A, static_cast<sometype2 *> (0));
I know that if we had these two overloaded functions of bar in the beginning, we would try to avoid the problem at the very beginning (without overloading) or we would write the correct calling code, but the overloaded function behind it might be a few months or a long time after we add it. Then the likelihood of our mistakes will increase a lot. It seems like what we're talking about here is nothing to do with C + + usually using the null pointer, OK, let's say our calling code is:
Foo.h
void Bar (Sometype1 A, sometype2 *b);
A.cpp
Bar (A, b);
B.cpp
Bar (A, NULL);
When the bar's overloaded function is added to the back, we'll see an error, but when it goes wrong, we find that the calling code in B.cpp can soon be ignored because we're using a NULL null pointer, which should be called void Bar (Sometype1 A, Sometype2 *b) This overloaded function ah. In fact, NULL in C + + is 0, write null this will make you less alert, because null is not enough "obvious", and here if the use of a null pointer, it will be enough "obvious", because 0 is a null pointer, it is an integer constant.
In C + +, using zero as a null pointer can make you more alert by shorting pointers with NULL.
Nullptr for C + + 11
Although we have shown above that 0 is more alert than NULL, we do not avoid this problem. This time nullptr C + + 11 is a good solution to this problem, we use nullptr in C + + 11 to represent null pointers, so the earliest code is this,
Foo.h
void Bar (Sometype1 A, sometype2 *b);
A.cpp
Bar (A, b);
B.cpp
Bar (A, nullptr);
After we added the bar's overloads later, the code was:
Foo.h
void Bar (Sometype1 A, sometype2 *b);
void Bar (Sometype1 A, int i);
A.cpp
Bar (A, b);
B.cpp
Bar (A, nullptr);
At this point, our code will run correctly as expected.
In the absence of C + + 11 nullptr, how do we resolve to avoid this problem? We can implement one ourselves ("imperfect C + +" has an implementation):
Const
Class nullptr_t
{
Public
Template<class t>
Inline operator t* () const
{return 0;}
Template<class C, Class t>
Inline operator T C::* () const
{return 0;}
Private
void operator& () const;
} nullptr = {};
Although this thing has been discussed many times, but I think it is necessary to discuss again, after all, before C + + 11 has not been popularized, we should still know how to avoid problems, how quickly find the problem.
C++11 NULL, 0, nullptr