Back to Item 30: Avoid member functions that return non-const pointers or references to members less accessible than themselves.
Continue to Item 32: Postpone variable definitions as long as possible.

Item 31: Never return a reference to a local object or to a dereferenced pointer initialized by `new` within the function.

This Item may sound complicated, but it's not. It's simple common sense. Really. Honest. Trust me.

Consider first the matter of returning a reference to a local object. The problem here is that local objects are just that, local. That means they're constructed when they're defined, and they're destructed when they go out of scope. Their scope, however, is that of the function body in which they're located. When the function returns, control leaves its scope, so the objects local to that function are automatically destructed. As a result, if you return a reference to a local object, that local object has been destructed before the caller of the function ever gets its computational hands on it.

This problem usually raises its ugly head when you try to improve the efficiency of a function by returning its result by reference instead of by value. The following example is the same as the one in Item 23, which pursues in detail the question of when you can return a reference and when you can't:

    class Rational {          // class for rational numbers
    public:
      Rational(int numerator = 0, int denominator = 1);
      ~Rational();

      ...

    private:
      int n, d;               // numerator and denominator

    // notice that operator* (incorrectly) returns a reference
    friend const Rational& operator*(const Rational& lhs,
                                     const Rational& rhs);
    };

    // an incorrect implementation of operator*
    inline const Rational& operator*(const Rational& lhs,
                                     const Rational& rhs)
    {
      Rational result(lhs.n * rhs.n, lhs.d * rhs.d);
      return result;
    }

Here, the local object `result` is constructed upon entry into the body of `operator*`. However, local objects are automatically destroyed when they go out of scope. `result` will go out of scope after execution of the `return` statement, so when you write this,

    Rational two = 2;

    Rational four = two * two;         // same as
                                       // operator*(two, two)

what happens during the function call is this:

1. The local object `result` is constructed.
2. A reference is initialized to be another name for `result`, and this reference is squirreled away as `operator*`'s return value.
3. The local object `result` is destroyed, and the space it used to occupy on the stack is made available for use by other parts of the program or by other programs.
4. The object `four` is initialized using the reference of step 2.

Everything is fine until step 4, at which point there occurs, as they say in the highest of high-tech circles, "a major lossage." The reference initialized in step 2 ceased to refer to a valid object as of the end of step 3, so the outcome of the initialization of object `four` is completely undefined.

The lesson should be clear: don't return a reference to a local object.

"Okay," you say, "the problem is that the object I want to use goes out of scope too soon. I can fix that. I'll just call `new` instead of using a local object." Like this:

    // another incorrect implementation of operator*
    inline const Rational& operator*(const Rational& lhs,
                                     const Rational& rhs)
    {
      // create a new object on the heap
      Rational *result =
        new Rational(lhs.n * rhs.n, lhs.d * rhs.d);

      // return it
      return *result;
    }

This approach does indeed avoid the problem of the previous example, but it introduces a new one in its place. To avoid a memory leak in your software, you know you must ensure that `delete` is applied to every pointer conjured up by `new`, but ay, there's the rub: who's to make the matching call to `delete` for this function's use of `new`?

Clearly, the caller of `operator*` must see to it that `delete` is applied. Clear, yes, and even easy to document, but nonetheless the cause is hopeless. There are two reasons for this pessimistic assessment.

First, it's well-known that programmers, as a breed, are sloppy. That doesn't mean that you're sloppy or that I'm sloppy, but rare is the programmer who doesn't work with someone who is — shall we say? — a little on the flaky side. What are the odds that such programmers — and we all know that they exist — will remember that whenever they call `operator*`, they must take the address of the result and then use `delete` on it? That is, they must use `operator*` like this:

    const Rational& four = two * two;      // get dereferenced
                                           // pointer; store it in
                                           // a reference
    ...

    delete &four;                          // retrieve pointer
                                           // and delete it

The odds are vanishingly small. Remember, if only a single caller of `operator*` fails to follow the rules, you have a memory leak.

Returning dereferenced pointers has a second, more serious, problem, because it persists even in the presence of the most conscientious of programmers. Often, the result of `operator*` is a temporary intermediate value, an object that exists only for the purposes of evaluating a larger expression. For example:

    Rational one(1), two(2), three(3), four(4);
    Rational product;

    product = one * two * three * four;

Evaluation of the expression to be assigned to `product` requires three separate calls to `operator*`, a fact that becomes more evident when you rewrite the expression in its equivalent functional form:

    product = operator*(operator*(operator*(one, two), three), four);

You know that each of the calls to `operator*` returns an object that needs to be deleted, but there is no possibility of applying `delete`, because none of the returned objects has been saved anywhere.

The only solution to this difficulty is to ask clients to code like this:

    const Rational& temp1 = one * two;
    const Rational& temp2 = temp1 * three;
    const Rational& temp3 = temp2 * four;

    delete &temp1;
    delete &temp2;
    delete &temp3;

Do that, and the best you can hope for is that people will ignore you. More realistically, you'd be skinned alive, or possibly sentenced to ten years hard labor writing microcode for waffle irons and toaster ovens.

Learn your lesson now, then: writing a function that returns a dereferenced pointer is a memory leak just waiting to happen.

By the way, if you think you've come up with a way to avoid the undefined behavior inherent in returning a reference to a local object and the memory leak haunting the return of a reference to a heap-allocated object, turn to Item 23 and read why returning a reference to a local `static` object also fails to work correctly. It may save you the trouble of seeking medical care for the arm you're likely to strain trying to pat yourself on the back.

Back to Item 30: Avoid member functions that return non-const pointers or references to members less accessible than themselves.
Continue to Item 32: Postpone variable definitions as long as possible.