C++ FAQ Celebrating Twenty-One Years of the C++ FAQ!!!
(Click here for a personal note from Marshall Cline.)
Section 26:
[26.13] What should be returned from a function?

In practice, there are a lot of cases. Here are a few of them in random order:

  • void — if you don't need a return value, don't return one.
  • local by value — it's the simplest, and with a little care NRVO maximizes performance.
  • local by pointer or reference — NOT!. Please don't do this.
  • data member by value — excellent choice if the function is a non-static member function, and if the data member can be copied relatively quickly, e.g., int. If the data member is something that is slow to copy, this has a performance penalty if you call this member function in the inner loop of a CPU-bound application.
  • data member by pointer — okay, but make sure you don't want to return it by reference, and make sure you use Foo const* or const Foo* if you don't want the caller to modify the data member. Since callers might store the pointer rather than copy the data member, you should warn callers in the member function's "contract" that they must not use the returned pointer after the this-object dies.
  • data member by reference-to-nonconst — okay, but this allows the caller to make changes to your object's data member without your class "seeing" the change. If you have a "set" method that changes this data member, use either a reference-to-const or by-value instead. Another thing: since callers might store the reference rather than copy the data member, you should warn callers in the member function's "contract" that they must not use the returned reference after the this-object dies.
  • data member by reference-to-const — okay, but it does allow your users to see the data type of your member variables. That means if you ever need to change the type of your member variables, the change might break the code that uses your class, and that's one of the main points of encapsulation. You can ameliorate that risk by exposing a public typedef for the type of that member variable (and therefore the type of the reference-to-const return value), and by warning your users that they should use the typedef rather than the raw, underlying type. Another reality is that if the caller captures this reference, as opposed to copying the object, then the underlying referent might change "under the caller's nose," even though the type is reference-to-const. Because a lot of programmers are surprised by that, it's smart to warn callers in the member function's "contract." You should also warn callers to discard the returned reference once the this-object has died.
  • shared_ptr to a member that was allocated via new — this has tradeoffs that are very similar to those of returning a member by pointer or by reference; see those bullets for the tradeoffs. The advantage is that callers can legitimately hold onto and use the returned pointer after the this-object dies.
  • local auto_ptr or shared_ptr to freestore-allocated copy of the datum. This is useful for polymorphic objects, since it lets you have the effect of return-by-value yet without the "slicing" problem. The performance needs to be evaluated on a case-by-case basis.
  • others — this list is by way of example and not by way of exclusion. In other words, this is just a starting point, not an ending point.

Murphy's Law basically guarantees that your particular needs will fall under the last bullet, rather than any of the earlier bullets Good.