Suppose that Foo is a rather large data structure. How should I write a const virtual function that returns an instance of Foo, if I don’t know whether the inherited classes will store the instance of Foo internally; thus, allowing a return by reference. If I can’t store it internally, my understanding is I can’t return a const reference to it because it will be a temporary. Is this correct? The two options are:
virtual Foo foo() const { ... }
virtual Foo const & foo() const { ... }
Here’s a related question but from a different angle.
You’re interested in the difference between a value return and a const reference return solely as a matter of optimization, but it isn’t. There’s a fundamentally different meaning between returning a different value each time, vs. returning a reference each time, quite possibly to the same object, which quite possibly could be modified:
The caller needs to know which it is, both because the programmer needs to know the meaning and because the compiler needs to know the calling convention, so you can’t mix them in different overrides of the same virtual function. If some derived classes want to do one, and some want to do the other, then that’s tough luck, they can’t, any more than one can return an
intand another afloat.You could perhaps return a
shared_ptr. That way, the derived classes that “want” to return a reference can create ashared_ptrwith a deleter that does nothing (but beware – theshared_ptrwill dangle if the original object is destroyed, and that’s not what you normally expect from a returnedshared_ptr. So if it makes sense for theFooto outlive the object it came from then it would be better for the class to dynamically allocate it, hold it via ashared_ptr, and return a copy of that, rather than a do-nothing deleter). The derived classes that “want” to return a value can allocate a new one each time. SinceFoois “rather large”, hopefully the cost of theshared_ptrand the dynamic allocation isn’t too painful compared with what you’d do anyway to create a new value to return.Another possibility is to turn
Foointo a small pImpl-style class that references a rather large data structure. If everything involved is immutable, then the “want to return a reference” case can share the large data structure between multipleFooinstances. Even if it isn’t, you can think about copy-on-write.