1

So, after taking 20 years off from C++, I have gotten back into it. I for the life of me cannot wrap my head around this issue. I am working with [at work] classes were I pass address references, rather than pointer references. This little foo() example below, why cannot I not return NULL or nullptr? What rule am I violating that I am forgetting?

int& foo(int &i)
{
  if (i > 10)
  {
    // or return nullptr;
    return NULL;
  }
  return i;
}
  • 1
    You're violating the rule that references can't be NULL. – nobody Feb 22 '15 at 15:35
  • You can't return `nullptr` because it's of pointer type, but `int&` declares the return type to be of reference type. – Emil Laine Feb 22 '15 at 15:35
  • 1
    C++ has no notion of "address". Nor "pointer references", at least in the way you seem to mean it. I suggest you read up on the difference between pointers and references. – Sneftel Feb 22 '15 at 15:37
  • 1
    @Sneftel: I'd say a "pointer reference" is just a colloquial name for a "reference to a pointer", isn't it? – Christian Hackl Feb 22 '15 at 15:45
  • I have no idea what "address references" and "pointer references" are. What book are you using? C++ as a standardised language hasn't even existed for 20 years, y'know... You should pretend that you've never even heard of C++ and read a C++ book to learn the language before asking silly questions! – Lightness Races in Orbit Feb 22 '15 at 18:46
  • @ChristianHackl As I mentioned, not the way the OP seems to mean it. – Sneftel Feb 22 '15 at 19:01

5 Answers5

1

why cannot I not return NULL or nullptr?

Because you have declared the function to return a reference to an int. References must always "point" to an actual int that exists. A nullptr is therefore not a valid value. (A null pointer is not convertible to a reference to int, it's only convertible to a pointer to int.)

Solution 1:

Declare the function to return a pointer to an int:

int* foo(int &i)
{
  if (i > 10)
  {
    return nullptr; // or NULL, or 0. (Since NULL is a macro expanding to `0` or `nullptr` anyway.)
  }
  return &i; // Return the address of i, aka a pointer to i.
}

Solution 2:

Declare an int value that is semantically identical to returning a null value.

int& foo(int &i)
{
  static int nullValue = 0;
  if (i > 10)
  {
    // or return nullptr;
    return nullValue;
  }
  return i;
}

Now every time i > 10 is true, the function will return a reference to the static local variable which is equal to 0 (you can change the actual value if needed).

Of course, if return i returns the a value identical to nullValue, then the function caller can't know whether the function returned a reference to the nullValue or some actual value i.

Emil Laine
  • 41,598
  • 9
  • 101
  • 157
1

There is no such thing as "address references". There are "references", and they are different from pointers. C++ references are a very powerful language feature absent from many other languages (e.g. C or Java).

A reference is best pictured as a different name for an existing object. Or better yet, as the object itself. A reference is the object.

That's not at all like a pointer. A pointer is itself an object which happens to point to something else (or to nothing).

They do it for performance reasons.

No, they don't. If they said this, then it doesn't make sense. You don't use references for performance (at least not non-const references), you use them for correctness.

int& foo(int &i)
{
  if (i > 10)
  {
    // or return nullptr;
    return NULL;
  }
  return i;
}

There is no such thing as "null references". Remember, a reference is the object. So what your foo function here returns is actually the object itself. Not a pointer to it, not its address, but the object itself.

And what object would NULL or nullptr be? It doesn't make sense. There cannot be an object which is nothing.

If you need to be able to have a special "nothing" state in your business logic, then you can use something like boost::optional. Or perhaps you really want a pointer, after all. It depends.

rather than pointer references.

Pointer references exist, but they are not related to your example.

Here is a pointer reference:

int main()
{
    int x = 0;
    int* ptr = &x;
    int*& y = ptr; // "y" is now a different name for "ptr"
}
Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
1

You might find this answer insightful.

Short answer: In C++ a reference can never be NULL (or any version of NULL like nullptr) because it must always be safe to de-reference.

Community
  • 1
  • 1
Jens
  • 8,423
  • 9
  • 58
  • 78
0

In C++ NULL is implementation defined but usually it is just integer:

#define NULL 0

or

#define NULL nullptr // since C++11

In both cases the error is type mismatch:

error: invalid initialization of non-const reference of type 'int&'
       from an rvalue of type 'int'
       #define NULL 0
                    ^
4pie0
  • 29,204
  • 9
  • 82
  • 118
  • Thanks for this. After reading both the first and second answer I understand what I was doing wrong. This helped me a lot. – Joshua Carnifexia Feb 22 '15 at 15:44
  • Even worse, if `NULL` is defined as `0`, then `return NULL` will return a reference to a *local variable* which will be destroyed when the function exits. – Emil Laine Feb 22 '15 at 15:45
  • @zenith not true, if #define NULL 0 it doesn't compile, and the error thrown is as I pasted. It is so to prevent from mistake that you mentioned. – 4pie0 Feb 22 '15 at 15:48
  • @AB_ You are right, my mistake. – Emil Laine Feb 22 '15 at 15:50
0

Null references are not allowed - "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 bitfield. ]". Source: http://en.wikipedia.org/wiki/Reference_%28C%2B%2B%29

robz
  • 1
  • 1