⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch08.htm

📁 vc的电子书
💻 HTM
📖 第 1 页 / 共 5 页
字号:
to the free store, which is sometimes referred to as the heap.</P>
<P>The problem with local variables is that they don't persist: When the function
returns, the local variables are thrown away. Global variables solve that problem
at the cost of unrestricted access throughout the program, which leads to the creation
of code that is difficult to understand and maintain. Putting data in the free store
solves both of these problems.</P>
<P>You can think of the free store as a massive section of memory in which thousands
of sequentially numbered cubbyholes lie waiting for your data. You can't label these
cubbyholes, though, as you can with the stack. You must ask for the address of the
cubbyhole that you reserve and then stash that address away in a pointer.</P>
<P>One way to think about this is with an analogy: A friend gives you the 800 number
for Acme Mail Order. You go home and program your telephone with that number, and
then you throw away the piece of paper with the number on it. If you push the button,
a telephone rings somewhere, and Acme Mail Order answers. You don't remember the
number, and you don't know where the other telephone is located, but the button gives
you access to Acme Mail Order. Acme Mail Order is your data on the free store. You
don't know where it is, but you know how to get to it. You access it by using its
address--in this case, the telephone number. You don't have to know that number;
you just have to put it into a pointer (the button). The pointer gives you access
to your data without bothering you with the details.</P>
<P>The stack is cleaned automatically when a function returns. All the local variables
go out of scope, and they are removed from the stack. The free store is not cleaned
until your program ends, and it is your responsibility to free any memory that you've
reserved when you are done with it.</P>
<P>The advantage to the free store is that the memory you reserve remains available
until you explicitly free it. If you reserve memory on the free store while in a
function, the memory is still available when the function returns.</P>
<P>The advantage of accessing memory in this way, rather than using global variables,
is that only functions with access to the pointer have access to the data. This provides
a tightly controlled interface to that data, and it eliminates the problem of one
function changing that data in unexpected and unanticipated ways.</P>
<P>For this to work, you must be able to create a pointer to an area on the free
store and to pass that pointer among functions. The following sections describe how
to do this.
<H4 ALIGN="CENTER"><A NAME="Heading22"></A><FONT COLOR="#000077">new</FONT></H4>
<P>You allocate memory on the free store in C++ by using the <TT>new</TT> keyword.
<TT>new</TT> is followed by the type of the object that you want to allocate so that
the compiler knows how much memory is required. Therefore, <TT>new unsigned short
int</TT> allocates two bytes in the free store, and <TT>new long</TT> allocates four.</P>
<P>The return value from <TT>new</TT> is a memory address. It must be assigned to
a pointer. To create an <TT>unsigned</TT> <TT>short</TT> on the free store, you might
write</P>
<PRE><FONT COLOR="#0066FF">unsigned short int * pPointer;
pPointer = new unsigned short int;
</FONT></PRE>
<P>You can, of course, initialize the pointer at its creation with</P>
<PRE><FONT COLOR="#0066FF">unsigned short int * pPointer = new unsigned short int;
</FONT></PRE>
<P>In either case, <TT>pPointer</TT> now points to an <TT>unsigned short int</TT>
on the free store. You can use this like any other pointer to a variable and assign
a value into that area of memory by writing</P>
<PRE><FONT COLOR="#0066FF">*pPointer = 72;
</FONT></PRE>
<P>This means, &quot;Put 72 at the value in <TT>pPointer</TT>,&quot; or &quot;Assign
the value <TT>72</TT> to the area on the free store to which <TT>pPointer</TT> points.&quot;</P>
<P>If <TT>new</TT> cannot create memory on the free store (memory is, after all,
a limited resource) it returns the null pointer. You must check your pointer for
null each time you request new memory.


<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>WARNING:</B></FONT><B> </B>Each time you allocate memory
	using the <TT>new</TT> keyword, you must check to make sure the pointer is not null.
	
<HR>


</BLOCKQUOTE>

<H4 ALIGN="CENTER"><A NAME="Heading23"></A><FONT COLOR="#000077">delete</FONT></H4>
<P>When you are finished with your area of memory, you must call <TT>delete</TT>
on the pointer. <TT>delete</TT> returns the memory to the free store. Remember that
the pointer itself--as opposed to the memory to which it points--is a local variable.
When the function in which it is declared returns, that pointer goes out of scope
and is lost. The memory allocated with <TT>new</TT> is not freed automatically, however.
That memory becomes unavailable--a situation called a memory leak. It's called a
memory leak because that memory can't be recovered until the program ends. It is
as though the memory has leaked out of your computer.</P>
<P>To restore the memory to the free store, you use the keyword <TT>delete</TT>.
For example,</P>
<PRE><FONT COLOR="#0066FF">delete pPointer;
</FONT></PRE>
<P>When you delete the pointer, what you are really doing is freeing up the memory
whose address is stored in the pointer. You are saying, &quot;Return to the free
store the memory that this pointer points to.&quot; The pointer is still a pointer,
and it can be reassigned. Listing 8.4 demonstrates allocating a variable on the heap,
using that variable, and deleting it.


<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>WARNING:</B></FONT><B> </B>When you call <TT>delete</TT>
	on a pointer, the memory it points to is freed. Calling <TT>delete</TT> on that pointer
	again will crash your program! When you delete a pointer, set it to zero (null).
	Calling <TT>delete</TT> on a null pointer is guaranteed to be safe. For example:</P>
	<PRE><FONT COLOR="#0066FF">Animal *pDog = new Animal; delete pDog; //frees the memory    </FONT></PRE>

	<BLOCKQUOTE>
		<PRE><FONT COLOR="#0066FF">pDog = 0; //sets pointer to null    //... delete pDog; //harmless</FONT></PRE>

	</BLOCKQUOTE>
	<P>
<HR>


</BLOCKQUOTE>

<PRE></PRE>
<P><A NAME="Heading24"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 8.4. Allocating,
using, and deleting pointers.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">
1:     // Listing 8.4
2:     // Allocating and deleting a pointer
3:
4:     #include &lt;iostream.h&gt;
5:     int main()
6:     {
7:        int localVariable = 5;
8:        int * pLocal= &amp;localVariable;
9:        int * pHeap = new int;
10:       if (pHeap == NULL)
11:        {
12:            cout &lt;&lt; &quot;Error! No memory for pHeap!!&quot;;
13:            return 0;
14:        }
15:       *pHeap = 7;
16:       cout &lt;&lt; &quot;localVariable: &quot; &lt;&lt; localVariable &lt;&lt; &quot;\n&quot;;
17:       cout &lt;&lt; &quot;*pLocal: &quot; &lt;&lt; *pLocal &lt;&lt; &quot;\n&quot;;
18:       cout &lt;&lt; &quot;*pHeap: &quot; &lt;&lt; *pHeap &lt;&lt; &quot;\n&quot;;
19:       delete pHeap;
20:       pHeap = new int;
21:       if (pHeap == NULL)
22:       {
23:            cout &lt;&lt; &quot;Error! No memory for pHeap!!&quot;;
24:            return 0;
25:       }
26:       *pHeap = 9;
27:       cout &lt;&lt; &quot;*pHeap: &quot; &lt;&lt; *pHeap &lt;&lt; &quot;\n&quot;;
28:       delete pHeap;
29:       return 0;
<TT>30: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: localVariable: 5
*pLocal: 5
*pHeap: 7
*pHeap: 9
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis: </B></FONT>Line 7 declares and initializes
a local variable. Line 8 declares and initializes a pointer with the address of the
local variable. Line 9 declares another pointer but initializes it with the result
obtained from calling <TT>new int</TT>. This allocates space on the free store for
an <TT>int</TT>. Line 10 verifies that memory was allocated and the pointer is valid
(not null). If no memory can be allocated, the pointer is null and an error message
is printed.<BR>
To keep things simple, this error checking often won't be reproduced in future programs,
but you must include some sort of error checking in your own programs.</P>
<P>Line 15 assigns the value <TT>7</TT> to the newly allocated memory. Line 16 prints
the value of the local variable, and line 17 prints the value pointed to by <TT>pLocal</TT>.
As expected, these are the same. Line 19 prints the value pointed to by <TT>pHeap</TT>.
It shows that the value assigned in line 15 is, in fact, accessible.</P>
<P>In line 19, the memory allocated in line 9 is returned to the free store by a
call to <TT>delete</TT>. This frees the memory and disassociates the pointer from
that memory. <TT>pHeap</TT> is now free to point to other memory. It is reassigned
in lines 20 and 26, and line 27 prints the result. Line 28 restores that memory to
the free store.</P>
<P>Although line 28 is redundant (the end of the program would have returned that
memory) it is a good idea to free this memory explicitly. If the program changes
or is extended, it will be beneficial that this step was already taken care of.
<H3 ALIGN="CENTER"><A NAME="Heading25"></A><FONT COLOR="#000077">Memory Leaks</FONT></H3>
<P>Another way you might inadvertently create a memory leak is by reassigning your
pointer before deleting the memory to which it points. Consider this code fragment:</P>
<PRE><FONT COLOR="#0066FF">1:   unsigned short int * pPointer = new unsigned short int;
2:   *pPointer = 72;
3:   pPointer = new unsigned short int;
4:   *pPointer = 84;
</FONT></PRE>
<P>Line 1 creates <TT>pPointer</TT> and assigns it the address of an area on the
free store. Line 2 stores the value <TT>72</TT> in that area of memory. Line 3 reassigns
<TT>pPointer</TT> to another area of memory. Line 4 places the value <TT>84</TT>
in that area. The original area--in which the value <TT>72</TT> is now held--is unavailable
because the pointer to that area of memory has been reassigned. There is no way to
access that original area of memory, nor is there any way to free it before the program
ends.</P>
<P>The code should have been written like this:</P>
<PRE><FONT COLOR="#0066FF">1: unsigned short int * pPointer = new unsigned short int;
2: *pPointer = 72;
3: delete pPointer;
4: pPointer = new unsigned short int;
5: *pPointer = 84;
</FONT></PRE>
<P>Now the memory originally pointed to by <TT>pPointer</TT> is deleted, and thus
freed, in line 3.


<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>For every time in your program that
	you call <TT>new</TT>, there should be a call to <TT>delete</TT>. It is important
	to keep track of which pointer owns an area of memory and to ensure that the memory
	is returned to the free store when you are done with it. 
<HR>


</BLOCKQUOTE>

<H3 ALIGN="CENTER"><A NAME="Heading26"></A><FONT COLOR="#000077">Creating Objects
on the Free Store</FONT></H3>
<P>Just as you can create a pointer to an integer, you can create a pointer to any
object. If you have declared an object of type <TT>Cat</TT>, you can declare a pointer
to that class and instantiate a <TT>Cat</TT> object on the free store, just as you
can make one on the stack. The syntax is the same as for integers:</P>
<PRE><FONT COLOR="#0066FF">Cat *pCat = new Cat;
</FONT></PRE>
<P>This calls the default constructor--the constructor that takes no parameters.
The constructor is called whenever an object is created (on the stack or on the free
store).
<H3 ALIGN="CENTER"><A NAME="Heading27"></A><FONT COLOR="#000077">Deleting Objects</FONT></H3>
<P>When you call <TT>delete</TT> on a pointer to an object on the free store, that
object's destructor is called before the memory is released. This gives your class
a chance to clean up, just as it does for objects destroyed on the stack. Listing
8.5 illustrates creating and deleting objects on the free store.</P>
<P><A NAME="Heading28"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 8.5. Creating
and deleting objects on the free store.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">
1:    // Listing 8.5
2:    // Creating objects on the free store
3:
4:     #include &lt;iostream.h&gt;
5:
6:     class SimpleCat
7:     {
8:     public:
9:            SimpleCat();
10:             ~SimpleCat();
11     private:
12             int itsAge;
13        };
14
15        SimpleCat::SimpleCat()
16        {
17               cout &lt;&lt; &quot;Constructor called.\n&quot;;
18               itsAge = 1;
19        }
20
21        SimpleCat::~SimpleCat()
22        {
23               cout &lt;&lt; &quot;Destructor called.\n&quot;;
24        }
25
26        int main()
27        {
28               cout &lt;&lt; &quot;SimpleCat Frisky...\n&quot;;
29               SimpleCat Frisky;
30               cout &lt;&lt; &quot;SimpleCat *pRags = new SimpleCat...\n&quot;;
31               SimpleCat * pRags = new SimpleCat;
32               cout &lt;&lt; &quot;delete pRags...\n&quot;;
33               delete pRags;
34               cout &lt;&lt; &quot;Exiting, watch Frisky go...\n&quot;;
35        return 0;
<TT>36 }</TT></FONT>
<FONT COLOR="#0066FF">
Output: SimpleCat Frisky...
Constructor called.
SimpleCat *pRags = new SimpleCat..
Constructor called.
delete pRags...
Destructor called.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -