25

Is it possible to initialize a reference member to NULL in c++?
I'm trying to something like this:

class BigClass
{
private:
    Object m_inner;
public:
    const Object& ReadOnly;
    BigClass() : ReadOnly(NULL)
    {
      Do stuff.
    }
};

I know I can do this if I initialize "ReadOnly" to a real reference of an object, but when I want to put in there "NULL", i get the error:

"cannot convert from 'int' to 'const Object &'

How can I solve this?

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
Idov
  • 5,006
  • 17
  • 69
  • 106

5 Answers5

42

No, references cannot be NULL in C++.1

Possible solutions include:

  • using a pointer instead of a reference.
  • having a dummy Object instance that can be used to indicate "no object".

[1] From the C++11 standard:

[dcl.ref] [...] 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.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • @Magnus: Yep, don't do, it's undefined behaviour. – Xeo Jan 29 '12 at 19:56
  • @wandalen - Which part? – Oliver Charlesworth Jan 07 '17 at 12:51
  • @OliverCharlesworth reference is not magic thing. Reference could point on NULL. For example : Object& object = *( Object* ) NULL. – Kos Jan 08 '17 at 16:58
  • @wandalen - That won't compile. – Oliver Charlesworth Jan 09 '17 at 12:30
  • @OliverCharlesworth Object& object = * ( Object * ) NULL – Kos Jan 09 '17 at 14:40
  • It does, last time asterisks were deleted by stackoverflow, sorry. – Kos Jan 09 '17 at 14:42
  • @wandalen: Ok but that's now simply undefined behaviour. And the [C++ standard](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf) explicitly calls this out: "*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*". – Oliver Charlesworth Jan 09 '17 at 15:04
  • @OliverCharlesworth yes, it's not the most famous technique, and there are too many customs around this things. few programmers from the previous century made all their best to force the world to think in a way they like. they succeed :) only just. regards. – Kos Jan 09 '17 at 15:16
10

You cannot "solve" this. Use a pointer if you want to be able to have that member not point to anything.

References must be initialized to a real object, they cannot "point nowhere".

Mat
  • 202,337
  • 40
  • 393
  • 406
  • 4
    @EthanSteinberg: depends. Smart pointers usually involve ownership. Sometimes you just want to point to something without claiming ownership. Of course you could use a weak pointer, but this requires allocating the object on the heap: no stack allocated object, no attribute of a bigger object, etc... *Smart Pointers are **NOT** a panacea*. – Matthieu M. Jan 29 '12 at 19:22
9

It can be done but it is almost certainly an extremely bad idea. The way to do it is to dereference a suitably typed NULL pointer which already shows that it is a bad idea: you arrive at undefined behavior at this point which, however, typically tends to "work".

In C++ references are meant to always refer to an actual object. This is different to other programming languages where "references" are actually the equivalent of pointers in C++ (typically without things like pointer arithmetic). What you probably actually want (you unfortunately didn't say what you try to achieve it but asked about a solution to a problem which is probably part of a misguided approach) is to use a pointer instead:

Object const* const readOnly;
BigClass(): readOnly(0) {}
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • My favourite answer. I just had to debug a complex class, and needed to call a single function, with a certain object. 0 referenced all the references as described, constructed obj, ignored references, called function, fixed the problem, undid everything. Obviously not something you want to do permanently though. – Cookie Aug 01 '14 at 13:39
4

It's useful in writing unit-tests. That is the only place it should be done, but there, it's quite helpful.

 Bar& bar(*static_cast<Bar*>(0));
 MockClass mock; // derives from RealClass
 mock.foo(bar);

Here, I am testing code which uses MockClass, not MockClass itself.

It's not a panacea, but it can help. Also, GoogleMock might be your friend if you are mocking "concrete" classes.

struct Bar;
struct RealClass {
  int& x_;
  double& y_;
  RealClass(int& x, double& y) :x_(x), y_(y) {}
  virtual void foo(Bar&);
};
struct MockClass: public RealClass {
  MockClass(): RealClass(*(int*)0, *(double*)0) {}
  MOCK_METHOD1(foo, void(Bar&));
};
cdunn2001
  • 17,657
  • 8
  • 55
  • 45
  • Down-voters: Try this *without* using a reference to NULL. Very difficult! In case it's not obvious, we aim to test code which uses a `RealClass` and which calls `foo()` on that `RealClass`. We inject both the `RealClass` and the `Bar` instances. `MockClass` needs to call the constructor of `RealClass`, but the underlying data are never needed. This is a valid use-case, so stop down-voting. – cdunn2001 Dec 11 '15 at 15:13
  • If you need to write this kind of tests, I think you have a serious design problem. –  Dec 20 '15 at 01:43
  • Legacy code or not, introducing undefined behavior in unit tests is a terrible idea. –  Dec 24 '15 at 10:52
  • It's not undefined behavior. And it answers the question. Downvote the question, not the answer. – cdunn2001 Dec 24 '15 at 19:31
  • It is UB. (see http://stackoverflow.com/questions/7130878/at-what-point-does-dereferencing-the-null-pointer-become-undefined-behavior). –  Dec 25 '15 at 20:27
  • In practice, absense of behavior. If you switch to a compiler where it fails, delete the test. But you're right: It's worth advising against using this in production code. – cdunn2001 Jan 07 '16 at 00:32
  • 1
    Thanks @cdunn2001! It was very helpful for mocking unit testing my application with GTKmm. – Evandro Coan Nov 11 '18 at 18:30
3

Use a pointer:- const Object* pReadOnly;

QuentinUK
  • 2,997
  • 21
  • 20