egor_hm
egor_hm

Reputation: 280

Initialize member references correctly

class Temp {
    public : 
        Temp(X& x): x_(x) {}
        Temp(X& x, Y& y) : x_(x), y_(y) {}
        ...
    private:
        X& x_;
        Y& y_;
}

I got the error because in case of Temp(X& x): x_(x) the reference y_ is not initialized. What is the common practice to write such a class correctly ?

Upvotes: 11

Views: 10067

Answers (6)

Karl Knechtel
Karl Knechtel

Reputation: 61643

The common practice, in all honesty, is to not use references as data members of a struct or class.

Why do you think you want to do this? A reference is, conceptually, another name for an already existing thing. Objects are, well, objects. You ought to be able to create them out of whole cloth. Sometimes they'll have pointers (or instances of some smart pointer class) to other stuff that already exists, but at least the pointer itself is real data.

Upvotes: 2

Stephane Rolland
Stephane Rolland

Reputation: 39926

Having a data member that is a reference is a STRONG contract: It means you CANNOT have a nullptr or undefined object, your class Needs this object, the object needs to exist.

As a consequence your first constructor violates this strong contract, and accordingly cannot compile.

As karlphillip suggests: you should use pointers since you do not want to respect such a contract that assures that _y is always defined.

It is valid having references as member, if your class doesnt have sense without the pre-existence of the referenced objects.

Upvotes: 7

karlphillip
karlphillip

Reputation: 93468

I will suggest another approach, even though that may be not what you are looking for.

It doesn't use reference variables (memory pointers instead), it also doesn't use boost, but it will allow you to keep both constructors without spending any more memory resources.

#include <iostream>

class Temp
{
    public :
        Temp(int& x): x_(&x), y_(NULL) {}
        Temp(int& x, int& y) : x_(&x), y_(&y) {}
        void print() { std::cout << "*x_: " << *x_ << std::endl; }

    private:
        int* x_;
        int* y_;
};

int main()
{
    int x = 5;
    Temp tmp(x);

    tmp.print();

    return 0;
}

Upvotes: 11

wilhelmtell
wilhelmtell

Reputation: 58715

Eliminate the first constructor or eliminate the second reference. If you have a reference then you must initialize it right away. If you must provide a constructor that default-initializes the Y member then make the Y member a pointer or an automatic variable.

Upvotes: 0

Andrew White
Andrew White

Reputation: 53516

You have a reference to y_! References must be initialed and your first constructor does not. If you can't bind to y when the class is created you should probably use a pointer.

Upvotes: 1

Nim
Nim

Reputation: 33655

You cannot have reference members that aren't initialized! If this is the case, consider wrapping the reference in a boost::optional, then you can optionally construct the reference.

EDIT: here is the boost::optional approach...

class Temp {
    public : 
        Temp(X& x): x_(x) {}
        Temp(X& x, Y& y) : x_(x), y_(y) {}
        ...
    private:
        X& x_;
        boost::optional<Y&> y_; // by default this is constructed with none_t
}

Upvotes: 10

Related Questions