Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I store references in classes in c++? [closed]

When I was learning C++, I was told that if you want to have multiple classes reference the same object, you should give both a pointer to the object. In Modern C++, I'd probably interpret this as the object being a unique_ptr and the classes holding non-owning-raw-pointers.

Recently, my mentor at work suggested that you should only use pointers when you plan on having the store point to a different object or null at some point. Instead, you should store references in classes.

Reference member variables are a thing I've actually never seen before, so I was looking for advice on what the concerns were... It makes sense... You're saying that this reference is assumed to never be null... I guess the concern would then be that you couldn't /check/ for null. It would have to be an invariant of your class...

How about how this applies to using the references for polymorphism?


Update: The answer that I selected covers my questions pretty well, but I thought I'd clarify for future readers. What I was really looking for was an idea of the consequences of using a reference rather than a pointer as a class member. I realise that the way the question was phrased made it sound more like I was looking for opinions on the idea.

like image 265
Daviid Carol Avatar asked May 07 '16 09:05

Daviid Carol


2 Answers

Should I store references in classes in c++?

yes, why not. This question is IMO 'primarily opinion-based', so my answer is based on my own experience.

I use member references when I dont need what pointers have to offer, this way I limit possiblity that my class will be wrongly used. This means among other possibility to bind new value, assign nullptr, you cant take pointer to reference, you cannot use reference arithmetics - those features are missing in references. You should also remember that reference is not an object type, this means among others that if you put a reference as struct member, then it is no longer POD - i.e. you cannot use memcpy on it.

You should also remember that for classes which have non static reference member, compiler will not generate implicit constuctors.

For me this means references as variable members are mostly usefull when class is some kind of wrapper, or a holder. Below is an example which also shows an alternative implementation using pointer member type. This alternative implementation gives you no additional benefit to the reference one, and only makes it possible to introduce Undefined Behaviour.

struct auto_set_false {
   bool& var;
   auto_set_false(bool& v) : var(v) {}
   ~auto_set_false() { var = false; }
};

struct auto_set_false_ptr {
   bool* var;
   auto_set_false_ptr(bool* v) : var(v) {}
   ~auto_set_false_ptr() { *var = false; }
};

int main()
{
    // Here auto_set_false looks quite safe, asf instance will always be
    // able to safely set nval to false. Its harder (but not imposible) to 
    // produce code that would cause Undefined Bahaviour. 
    bool nval = false;
    auto_set_false asf(nval);

    bool* nval2 = new bool(true);
    auto_set_false_ptr asf2(nval2);    
    // lots of code etc. and somewhere in this code a statement like:
    delete nval2;
    // UB
}
like image 66
marcinj Avatar answered Sep 23 '22 00:09

marcinj


It is generally not a good idea to store references in a class because the class cannot be default constructed, copy assigned, move assigned, and the member cannot be changed (the reference cannot be rebound).

That renders the class uncopieable. It therefore cannot be copied, moved or placed in most containers. The far more flexible and less surprising solution is to store a pointer or a std::refernce_wrapper.

like image 36
Thomas Avatar answered Sep 23 '22 00:09

Thomas