Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I'll assume that by class method you mean member function. And that by "return by reference" you mean "return reference to member data". This is mainly as opposed to returning a reference to local, which is clearly wrong.</p> <p><strong>When should you return a reference to member data, and when the data itself ?</strong></p> <p>By default, you should be returning the data itself (aka "by value"). This avoids several problems with returning a reference:</p> <ul> <li><p>Users storing the reference and becoming dependant on the <strong>lifetime</strong> of your members, without considering how long the containing object (your object) will live. Leads to dangling pointers.</p></li> <li><p>User code becoming dependant on the exact <strong>return type</strong>. For example, you use a <code>vector&lt;T&gt;</code> for implementation (and that's what your getter returns). User code like "<code>vector&lt;T&gt; foo = obj.getItems()</code>" appears. Then you change your implementation (and getter) to use a <code>deque&lt;T&gt;</code> -- user code breaks. If you had been returning by value, you could simply make the getter create a local vector, copy the data over from the member deque, and return the result. Quite reasonable for small-sized collections. [*]</p></li> </ul> <p>So when should you return a reference instead?</p> <ul> <li>You can consider it when the returned object is huge (<code>Image</code>) or non-copyable (<code>boost::signal</code>). But, as always, you can instead opt for the more OOP pattern of having your class <strong>do</strong> stuff rather than have stuff <strong>hanging from it</strong>. In the <code>Image</code> case, you can provide a <code>drawCircle</code> member function, rather than returning <code>Image&amp;</code> and having your users draw a circle on it.</li> <li>When your data is logically owned by your user, and you're just holding it for him. Consider std collections: <code>vector&lt;T&gt;::operator[]</code> returns a <em>reference</em> to T because that's what I want to get at: my exact object, not a copy of it.</li> </ul> <hr> <p>[*] There is a better way to ensure future-proof code. Rather than returning a vector (by ref of by value) return a pair of iterators to your vector -- a beginning and an ending one. This lets your users do <em>everything</em> they normally do with a deque or a vector, but independent of the actual implementation. Boost provides <code>boost::iterator_pair</code> for this purpose. As a perk, it also has operator[] overloaded, so you can even do "<code>int i = obj.getItems()[5]</code>" rather than "<code>int i = obj.getItems().begin()[5]</code>".</p> <p>This solution is generalizable to any situation which allows you to treat types generically. For example, if you keep a <code>Dog</code> member but your users only need to know it's an <code>Animal</code> (because they only call <code>eat()</code> and <code>sleep()</code>), return an <em>Animal</em> reference/pointer to a freestore-allocated copy of your dog. Then when you decide dogs are weaklings and you really need a wolf for the implementation, user code won't break.</p> <p>This sort of <em>information-hiding</em> does more than ensure future-compatibility. It also helps keep your design clean.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload