C++

Returning a Reference to an Object on the Heap

You might be tempted to solve the problem in Listing 9.13 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 9.14 illustrates this problem.

Listing 9.14. Memory leaks.

1: // Listing 9.14

2: // Resolving memory leaks

3: #include <iostream.h>

4:

5: class SimpleCat

6: {

7: public:

8: SimpleCat (int age, int weight);

9: ~SimpleCat() {}

10: int GetAge() { return itsAge; }

11: int GetWeight() { return itsWeight; }

12:

13 private:

14: int itsAge;

15: int itsWeight;

16: };

17:

18: SimpleCat::SimpleCat(int age, int weight):

19: itsAge(age), itsWeight(weight) {}

20:

21: SimpleCat & TheFunction();

22:

23: int main()

24: {

25: SimpleCat & rCat = TheFunction();

26: int age = rCat.GetAge();

27: cout << "rCat is " << age << " years old!\n";

28: cout << "&rCat: " << &rCat << endl;

29: // How do you get rid of that memory?

30: SimpleCat * pCat = &rCat;

31: delete pCat;

32: // Uh oh, rCat now refers to ??

33: return 0;

34: }

35:

36: SimpleCat &TheFunction()

37: {

38: SimpleCat * pFrisky = new SimpleCat(5,9);

39: cout << "pFrisky: " << pFrisky << endl;

40: return *pFrisky;

41: }

OUTPUT: 

pFrisky: 0x2bf4

rCat is 5 years old!

&rCat: 0x2bf4

WARNING: This compiles, links, and appears to work. But it is a time bomb waiting to go off.

ANALYSIS: TheFunction() has been changed so that it no longer returns a reference to a local variable. Memory is allocated on the free store and assigned to a pointer on line 38. The address that pointer holds is printed, and then the pointer is dereferenced and the SimpleCat object is returned by reference. On line 25, the return of TheFunction() is assigned to a reference to SimpleCat, and that object is used to obtain the cat’s age, which is printed on line 27.

To prove that the reference declared in main() is referring to the object put on the free store 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 free store.

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 alias an actual object; if it references a null object (as this does now), the program is invalid.

NOTE: It cannot be overemphasized that a program with a reference to a null object may compile, but it is invalid and its performance is unpredictable.

There are actually three solutions to this problem. The first is to declare a SimpleCat object on line 25, and to return that cat from TheFunction by value. The second is to go ahead and declare the SimpleCat on the free store in TheFunction(), but have TheFunction() return a pointer to that memory. Then the calling function can delete the pointer when it is done.
The third workable solution, and the right one, is to declare the object in the calling function and then to pass it to TheFunction() by reference.

Back to Index