albeit there is a possible lazier solution:
a reference is (formally) just a slight syntactic sugar over a pointer.
(IOW: just define it as being a pointer... possibly just leaving a NULL
reference as undefined behavior).
In non-pathological usage, a C++ reference cannot be null. That's
caught at compile time, which is a *massive* win over introducing
another bit of undefined behaviour.
A C++ reference-to-T cannot be mistaken for the the start of any array
of T, or an iterator into a collection of T's, so you can't do pointer
arithmetic on them.
NULL pointer dereferences and incorrect pointer arithmetic are two of
the most common causes of bugs in C/C++ programs.
To say "you can't do anything with a reference that you can't do with
a pointer" is to miss the point. The things that you *can't* do to a
reference are a feature (but can do to a pointer).
In C, a pointer is one-or-more of "a reference to an object", "an
iterator into an array of objects", "the address of some memory", "a
reference to nothing".
In C++, a reference is "a reference to an object".
I don't consider that restriction to be "slight syntactic sugar". It
actually allows the compiler to do type checking so that the function
caller's and the function writer's intentions are the same.
Of course, they'll never be introduced to C, because C of the
minimalist nature of C. Introducing new types similar to old types -
regardless of the type safety advantages - will not happen.