Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 242
egor_hm Avatar asked Dec 13 '10 15:12

egor_hm


4 Answers

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.

like image 85
Karl Knechtel Avatar answered Oct 20 '22 17:10

Karl Knechtel


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;
}
like image 41
karlphillip Avatar answered Oct 20 '22 17:10

karlphillip


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
}
like image 37
Nim Avatar answered Oct 20 '22 15:10

Nim


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.

like image 39
Stephane Rolland Avatar answered Oct 20 '22 16:10

Stephane Rolland