|

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.
|