views:

644

answers:

12
struct Div
{
   int i;
   int j;
};   

class A
{
    public:
             A();
             Div& divs;
};

In my constructor definition, I have the following

A::A() : divs(NULL)
{}

I get the following error:

  Error72 error C2354: 
  'A::divs' : initialization of reference member requires a temporary variable
+5  A: 

For one, you can't have a NULL reference. As second, all variable references in a class must be initialized at construction time.

jldupont
how do i correct it?
aajkaltak
@varun: you need to initialize your reference to a valid object instance at time of construction (i.e. in your constructor).
jldupont
@varun: note that you can go for a pointer if that makes your life easier... or refactor.
jldupont
thanks guys for the response! i decided to go with pointer .. made my life much easier!
aajkaltak
... and how about accepting an answer then?
jldupont
+2  A: 

In "English": a reference refers to something. It cannot refer to nothing (null). That's why references are safer to use then pointers.

Abel
Not just in english. The exact same is true in C++.
jalf
lol, I meant "the rule of C++ written in common English" ;-)
Abel
+1  A: 

You should try and initialise your "divs" variable. You cannot have a reference refering to "nothing"...

Have a look here :

http://msdn.microsoft.com/en-us/library/bbt3ewya%28VS.80%29.aspx

Hope this help a bit!

Andy M
+6  A: 

divs is a reference, not a pointer. You can't set it to NULL, it has to point to an actual object of some kind. The best thing to do here is probably to define a static/global instance of Div that you arbitrarily define to be the "Null Div" (set its value to something you're unlikely ever to use) and initialize div to that. Something like this:

struct Div
{
   int i;
   int j;
};   

Div NULL_DIV = { INT_MAX, INT_MAX };

class A
{
    public:
             A();
             Div& divs;
};


A::A() : divs(NULL_DIVS)
{
}

Or, alternatively, just make divs a pointer instead of a reference.

*Note that you can't use a const reference unless you cast away the constness because by default the compiler won't allow you to assign a cosnt ref to a non-const ref.

Russell Newquist
you're initializing non-const ref with const object. Does it compile?
Arkadiy
Ah, good catch, no it doesn't. I'll update the answer.
Russell Newquist
+3  A: 

References have to reference something. There is no such thing as a null reference in the C++ language. If the member may not have a value, then it should be a pointer, or a boost::optional or some type like that.

A reference must be initialized to reference a valid object.

jalf
+13  A: 

A reference must be initialised to refer to something; it can't refer to nothing, so you can't default-construct a class that contains one (unless, as others suggest, you define a global "null" value). You will need a constructor that is given the Div to refer to:

explicit A(Div &d) : divs(d) {}

If you want it to be able to be "null", then you need a pointer, not a reference.

Mike Seymour
It is generally not true that you can't default-construct a class with a reference member. For example, the reference can be bound to an object declared at namespace scope ("global" object, in simpler words).
AndreyT
As noted, you can do a default constructor if you use a predefined variable (as in my example below).
Russell Newquist
You're both correct. However, I would advise against using a global "null" value - it can't be const, so the default behaviour would be to use a global object that any other instance of the class can change without notice.
Mike Seymour
+1  A: 

Keep in mind that once a reference is initialized to point to something, you cannot alter it to point to something else. If this is not the desired behavior, then you should use a pointer or a copy of the object instead.

qid
+1  A: 

As noted in other posts, references (Div&) cannot be null. So the most straightforward change you can make is to provide a reference in the constructor and initialize your reference member. Like this,

class A
{
    public:
             A(Div& inDivs);
             Div& divs;

};

public A::A( Div& inDivs )
: divs( inDivs )
{}
Phillip Ngan
+3  A: 

The compiler message is one of those messages that don't make sense from the language point of view, but reveal the inner workings of the compiler, the sequence in which its inner logic works.

In your case you are using an rvalue (NULL) to initialize a reference. When such initialization is allowed, the rvalue is converted to a temporary object, to which the reference will be bound. So, the compiler has realized it right away and informed you about the fact with a diagnostic message.

In reality though, the trick like that is only allowed for const references, so your code is broken, since the reference is not const in our case. Also, a struct reference, as the one in your code, cannot be initialized with NULL rvalue (which has integral type), so it is broken for that reason as well.

The compiler's message is rather misleading though. The text of the message seems to imply that it is illegal to initialize member references with temporary objects. In fact, this is legal in C++ (once the above problems are fixed), although it makes no sense. But, I guess, once ill-formed code is accompanied by at least some error message, it should be OK for everyone...

AndreyT
+2  A: 

Plain and simple:

A reference can never be NULL.

Marcin
A: 

why not to use just pointer and initialize it in the initialization list by the reference?

varnie
A: 
  class A
    {
        Div & ref(Div div) { return div; }
        public:
                 A() : divs(ref(Div())) {};
                 Div& divs;
    };
konstantin314