Question

Having read this:

Is the practice of returning a C++ reference variable, evil?

and a few other resources on references, I was wondering if something like this is OK or should I be returning a pointer?

#include <iostream>

class engine
{
public:
  int cc;
};


class car
{
protected:
  engine eng;

public:
  car (void) : eng()
  {
    eng.cc = 500;
  }

  const engine& get_engine(void) const
  {
    return eng;
  }
};


int main (void)
{
  car c = car();

  engine en = c.get_engine();


  std::cout << en.cc << std::endl;
}

Also:

What would be the difference if I changed the line

engine en = c.get_engine();

to

engine& en = c.get_engine();

both compile and give the same output but are there any subtle/not-so-subtle differences?

EDIT: as Vlad from Moscow pointed out, that last one should be const engine& en = c.get_engine();.

Was it helpful?

Solution

The answer depends on what you are trying to model:

  • If an engine cannot exist outside the context of its car, and if a car cannot exist without an engine, returning a reference is fine - This means that the car is going to exist at the time when you work with its engine.
  • If an engine can exist outside the context of its car, you would be better off returning a pointer (preferably, a smart pointer). This way deleting the corresponding car is not going to delete the engine.
  • Same goes if a car can exist without an engine: you need to return a pointer, because there is no such thing as null reference (hacks do not count here)

Of course these are only models of the reality - in reality, both cars without engines and engines without cars do exist. You can even swap engines between cars if they fit. However, modeling the reality to this level takes more effort on your part, so you need to make a decision on how far your model goes.

The difference between engine en = c.get_engine(); and engine &en = c.get_engine(); is that the first expression makes a copy of c's engine, while the second one references the engine in place. Among other things, this means that manipulations on the copy of the engine are not automatically reflected in the original, because they are not the same object. Another consequence is that a copy survives deletion of the car, while a reference does not.

OTHER TIPS

The difference is that in the second case the copy constructor will not be called.

Only you need to write

const engine& en = c.get_engine();

Your code is O'k.

From the SO post you referenced, the example given was:

int& getInt(void)
{
    int i;
    return i;
}

That is definitely not good. You are returning a reference to an object which will be gone when you return from the function.

In your case,

const engine& get_engine(void) const
{
  return eng;
}

That is a perfectly valid use of returning references to objects.

Use of

engine& en = c.get_engine();

must result in a compiler error.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top