[c++] Reference member variables as class members

In my place of work I see this style used extensively:-

#include <iostream>

using namespace std;

class A
{
public:
   A(int& thing) : m_thing(thing) {}
   void printit() { cout << m_thing << endl; }

protected:
   const int& m_thing; //usually would be more complex object
};


int main(int argc, char* argv[])
{
   int myint = 5;
   A myA(myint);
   myA.printit();
   return 0;
}

Is there a name to describe this idiom? I am assuming it is to prevent the possibly large overhead of copying a big complex object?

Is this generally good practice? Are there any pitfalls to this approach?

This question is related to c++ reference

The answer is


Member references are usually considered bad. They make life hard compared to member pointers. But it's not particularly unsual, nor is it some special named idiom or thing. It's just aliasing.


C++ provides a good mechanism to manage the life time of an object though class/struct constructs. This is one of the best features of C++ over other languages.

When you have member variables exposed through ref or pointer it violates the encapsulation in principle. This idiom enables the consumer of the class to change the state of an object of A without it(A) having any knowledge or control of it. It also enables the consumer to hold on to a ref/pointer to A's internal state, beyond the life time of the object of A. This is bad design. Instead the class could be refactored to hold a ref/pointer to the shared object (not own it) and these could be set using the constructor (Mandate the life time rules). The shared object's class may be designed to support multithreading/concurrency as the case may apply.


Is there a name to describe this idiom?

There is no name for this usage, it is simply known as "Reference as class member".

I am assuming it is to prevent the possibly large overhead of copying a big complex object?

Yes and also scenarios where you want to associate the lifetime of one object with another object.

Is this generally good practice? Are there any pitfalls to this approach?

Depends on your usage. Using any language feature is like "choosing horses for courses". It is important to note that every (almost all) language feature exists because it is useful in some scenario.
There are a few important points to note when using references as class members:

  • You need to ensure that the referred object is guaranteed to exist till your class object exists.
  • You need to initialize the member in the constructor member initializer list. You cannot have a lazy initialization, which could be possible in case of pointer member.
  • The compiler will not generate the copy assignment operator=() and you will have to provide one yourself. It is cumbersome to determine what action your = operator shall take in such a case. So basically your class becomes non-assignable.
  • References cannot be NULL or made to refer any other object. If you need reseating, then it is not possible with a reference as in case of a pointer.

For most practical purposes (unless you are really concerned of high memory usage due to member size) just having a member instance, instead of pointer or reference member should suffice. This saves you a whole lot of worrying about other problems which reference/pointer members bring along though at expense of extra memory usage.

If you must use a pointer, make sure you use a smart pointer instead of a raw pointer. That would make your life much easier with pointers.


It's called dependency injection via constructor injection: class A gets the dependency as an argument to its constructor and saves the reference to dependent class as a private variable.

There's an interesting introduction on wikipedia.

For const-correctness I'd write:

using T = int;

class A
{
public:
  A(const T &thing) : m_thing(thing) {}
  // ...

private:
   const T &m_thing;
};

but a problem with this class is that it accepts references to temporary objects:

T t;
A a1{t};    // this is ok, but...

A a2{T()};  // ... this is BAD.

It's better to add (requires C++11 at least):

class A
{
public:
  A(const T &thing) : m_thing(thing) {}
  A(const T &&) = delete;  // prevents rvalue binding
  // ...

private:
  const T &m_thing;
};

Anyway if you change the constructor:

class A
{
public:
  A(const T *thing) : m_thing(*thing) { assert(thing); }
  // ...

private:
   const T &m_thing;
};

it's pretty much guaranteed that you won't have a pointer to a temporary.

Also, since the constructor takes a pointer, it's clearer to users of A that they need to pay attention to the lifetime of the object they pass.


Somewhat related topics are: