You might be tempted to solve the problem in Listing 12.4 by having TheFunction() create Frisky on the heap. That way, when you return from TheFunction(), Frisky will still exist.
The problem with this approach is: What do you do with the memory allocated for Frisky when you are done with it? Listing 12.5 illustrates this problem.
![]() | This compiles, links, and appears to work. But it is a time bomb waiting to go off. |
On line 24, the return of TheFunction() is assigned to a reference to a SimpleCat, and that object is used to obtain the cat's age, which is printed on line 26.
To prove that the reference declared in main() is referring to the object put on the heap in TheFunction(), the address of operator is applied to rCat. Sure enough, it displays the address of the object it refers to, and this matches the address of the object on the heap.
So far, so good. But how will that memory be freed? You can't call delete on the reference. One clever solution is to create another pointer and initialize it with the address obtained from rCat. This does delete the memory and plugs the memory leak. One small problem, though: What is rCat referring to after line 31? As stated earlier, a reference must always be an alias for an actual object; if it references a null object (as this does now), the program is invalid.
![]() | It cannot be overemphasized that a program with a reference to a null object might compile, but it is invalid and its performance is unpredictable. |
There are actually two solutions to this problem. The first is to return a pointer to the memory created on line 37. Then the calling function can delete the pointer when it is done. To do this, change the return value of TheFunction to pointer (rather than reference) and return the pointer, rather than the dereferenced pointer:
SimpleCat * TheFunction() { SimpleCat * pFrisky = new SimpleCat(5,9); std::cout << "pFrisky: " << pFrisky << std::endl; return pFrisky; // return the pointer }
The alternative and more desirable solution is to declare the object in the calling function and then to pass it to TheFunction() by reference. The advantage of this alternative is that the function that allocates the memory (the calling function) is also the function that is responsible for de-allocating it, which, as you'll see in the next section, is preferable.
3.128.170.92