📄 ch11.htm
字号:
</FONT></PRE><P>For the sake of clarity, you could group the initializations with braces. Forexample,</P><PRE><FONT COLOR="#0066FF">int theArray[5][3] = { {1,2,3},{4,5,6},{7,8,9},{10,11,12},{13,14,15} };</FONT></PRE><P>The compiler ignores the inner braces, which make it easier to understand howthe numbers are distributed.</P><P>Each value must be separated by a comma, without regard to the braces. The entireinitialization set must be within braces, and it must end with a semicolon.</P><P>Listing 11.5 creates a two-dimensional array. The first dimension is the set ofnumbers from 0 to 5. The second dimension consists of the double of each value inthe first dimension.</P><P><A NAME="Heading24"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 11.5. Creatinga multidimensional array.</B></FONT></P><PRE><FONT COLOR="#0066FF">1: #include <iostream.h>2: int main()3: {4: int SomeArray[5][2] = { {0,0}, {1,2}, {2,4}, {3,6}, {4,8}};5: for (int i = 0; i<5; i++)6: for (int j=0; j<2; j++)7: {8: cout << "SomeArray[" << i << "][" << j << "]: ";9: cout << SomeArray[i][j]<< endl;10: }11:12: return 0;<TT>13: }</TT></FONT><FONT COLOR="#0066FF">Output: SomeArray[0][0]: 0SomeArray[0][1]: 0SomeArray[1][0]: 1SomeArray[1][1]: 2SomeArray[2][0]: 2SomeArray[2][1]: 4SomeArray[3][0]: 3SomeArray[3][1]: 6SomeArray[4][0]: 4SomeArray[4][1]: 8</FONT></PRE><P><FONT COLOR="#0000AA"><B>Analysis:</B></FONT><B> </B>Line 4 declares <TT>SomeArray</TT>to be a two-dimensional array. The first dimension consists of five integers; thesecond dimension consists of two integers. This creates a 5x2 grid, as Figure 11.4shows. <BR><A HREF="11zcp04.jpg" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/art/ch11/11zcp04.jpg"><BR></A><A NAME="Heading26"></A><A HREF="11zcp04.jpg" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/art/ch11/11zcp04.jpg"><FONT COLOR="#000077">Figure11.4.</FONT></A><FONT COLOR="#000077"> </FONT><I>A 5x2 array. </I><BR><BR>The values are initialized in pairs, although they could be computed as well. Lines5 and 6 create a nested <TT>for</TT> loop. The outer <TT>for</TT> loop ticks througheach member of the first dimension. For every member in that dimension, the inner<TT>for</TT> loop ticks through each member of the second dimension. This is consistentwith the printout. <TT>SomeArray[0][0]</TT> is followed by <TT>SomeArray[0][1]</TT>.The first dimension is incremented only after the second dimension is incrementedby 1. Then the second dimension starts over.<H3 ALIGN="CENTER"><A NAME="Heading27"></A><FONT COLOR="#000077">A Word About Memory</FONT></H3><P>When you declare an array, you tell the compiler exactly how many objects youexpect to store in it. The compiler sets aside memory for all the objects, even ifyou never use it. This isn't a problem with arrays for which you have a good ideaof how many objects you'll need. For example, a chess board has 64 squares, and catshave between 1 and 10 kittens. When you have no idea of how many objects you'll need,however, you must use more advanced data structures.</P><P>This book looks at arrays of pointers, arrays built on the free store, and variousother collections. Other more advanced data structures that solve large data storageproblems are beyond the scope of this book. Two of the great things about programmingare that there are always more things to learn and that there are always more booksfrom which to learn.<H3 ALIGN="CENTER"><A NAME="Heading28"></A><FONT COLOR="#000077">Arrays of Pointers</FONT></H3><P>The arrays discussed so far store all their members on the stack. Usually stackmemory is severely limited, whereas free store memory is far larger. It is possibleto declare each object on the free store and then to store only a pointer to theobject in the array. This dramatically reduces the amount of stack memory used. Listing11.6 rewrites the array from Listing 11.4, but it stores all the objects on the freestore. As an indication of the greater memory that this enables, the array is expandedfrom 5 to 500, and the name is changed from <TT>Litter</TT> to <TT>Family</TT>.</P><P><A NAME="Heading29"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 11.6. Storingan array on the free store.</B></FONT></P><PRE><FONT COLOR="#0066FF">1: // Listing 11.6 - An array of pointers to objects2:3: #include <iostream.h>4:5: class CAT6: {7: public:8: CAT() { itsAge = 1; itsWeight=5; } 9: ~CAT() {} // destructor10: int GetAge() const { return itsAge; }11: int GetWeight() const { return itsWeight; }12: void SetAge(int age) { itsAge = age; }13:14: private:15: int itsAge;16: int itsWeight;17: };18:19: int main()20: {21: CAT * Family[500];22: int i;23: CAT * pCat;24: for (i = 0; i < 500; i++)25: {26: pCat = new CAT;27: pCat->SetAge(2*i +1);28: Family[i] = pCat;29: }30:31: for (i = 0; i < 500; i++)32: {33: cout << "Cat #" << i+1 << ": ";34: cout << Family[i]->GetAge() << endl;35: }36: return 0;<TT>37: }</TT></FONT><FONT COLOR="#0066FF">Output: Cat #1: 1Cat #2: 3Cat #3: 5...Cat #499: 997Cat #500: 999</FONT></PRE><DL> <DD><FONT COLOR="#0066FF"></FONT></DL><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The <TT>CAT</TT> object declaredin lines 5-17 is identical with the <TT>CAT</TT> object declared in Listing 11.4.This time, however, the array declared in line 21 is named <TT>Family</TT>, and itis declared to hold 500 pointers to <TT>CAT</TT> objects.</P><P>In the initial loop (lines 24-29), 500 new <TT>CAT</TT> objects are created onthe free store, and each one has its age set to twice the index plus one. Therefore,the first <TT>CAT</TT> is set to <TT>1</TT>, the second <TT>CAT</TT> to <TT>3</TT>,the third <TT>CAT</TT> to <TT>5</TT>, and so on. Finally, the pointer is added tothe array.</P><P>Because the array has been declared to hold pointers, the pointer--rather thanthe dereferenced value in the pointer--is added to the array.</P><P>The second loop (lines 31 and 32) prints each of the values. The pointer is accessedby using the index, <TT>Family[i]</TT>. That address is then used to access the <TT>GetAge()</TT>method.</P><P>In this example, the array <TT>Family</TT> and all its pointers are stored onthe stack, but the 500 <TT>CAT</TT>s that are created are stored on the free store.<H3 ALIGN="CENTER"><A NAME="Heading31"></A><FONT COLOR="#000077">Declaring Arrayson the Free Store</FONT></H3><P>It is possible to put the entire array on the free store, also known as the heap.You do this by calling <TT>new</TT> and using the subscript operator. The resultis a pointer to an area on the free store that holds the array. For example,</P><PRE><FONT COLOR="#0066FF">CAT *Family = new CAT[500];</FONT></PRE><P>declares <TT>Family</TT> to be a pointer to the first in an array of 500 <TT>CAT</TT>s.In other words, <TT>Family</TT> points to--or has the address of--<TT>Family[0]</TT>.</P><P>The advantage of using <TT>Family</TT> in this way is that you can use pointerarithmetic to access each member of <TT>Family</TT>. For example, you can write</P><PRE><FONT COLOR="#0066FF">CAT *Family = new CAT[500];CAT *pCat = Family; //pCat points to Family[0]pCat->SetAge(10); // set Family[0] to 10pCat++; // advance to Family[1]pCat->SetAge(20); // set Family[1] to 20</FONT></PRE><P>This declares a new array of 500 <TT>CAT</TT>s and a pointer to point to the startof the array. Using that pointer, the first <TT>CAT</TT>'s <TT>SetAge()</TT> functionis called with a value of <TT>10</TT>. The pointer is then incremented to point tothe next <TT>CAT</TT>, and the second <TT>Cat</TT>'s <TT>SetAge()</TT> method isthen called.<H3 ALIGN="CENTER"><A NAME="Heading32"></A><FONT COLOR="#000077">A Pointer to anArray Versus an Array of Pointers</FONT></H3><P>Examine these three declarations:</P><PRE><FONT COLOR="#0066FF">1: Cat FamilyOne[500]2: CAT * FamilyTwo[500];3: CAT * FamilyThree = new CAT[500];</FONT></PRE><P><TT>FamilyOne</TT> is an array of 500 <TT>CAT</TT>s. <TT>FamilyTwo</TT> is anarray of 500 pointers to <TT>CAT</TT>s. <TT>FamilyThree</TT> is a pointer to an arrayof 500 <TT>CAT</TT>s.</P><P>The differences among these three code lines dramatically affect how these arraysoperate. What is perhaps even more surprising is that <TT>FamilyThree</TT> is a variantof <TT>FamilyOne</TT>, but is very different from <TT>FamilyTwo</TT>.</P><P>This raises the thorny issue of how pointers relate to arrays. In the third case,<TT>FamilyThree</TT> is a pointer to an array. That is, the address in <TT>FamilyThree</TT>is the address of the first item in that array. This is exactly the case for <TT>FamilyOne</TT>.<H3 ALIGN="CENTER"><A NAME="Heading33"></A><FONT COLOR="#000077">Pointers and ArrayNames</FONT></H3><P>In C++ an array name is a constant pointer to the first element of the array.Therefore, in the declaration</P><PRE><FONT COLOR="#0066FF">CAT Family[50];</FONT></PRE><P><TT>Family</TT> is a pointer to <TT>&Family[0]</TT>, which is the addressof the first element of the array <TT>Family</TT>.</P><P>It is legal to use array names as constant pointers, and vice versa. Therefore,<TT>Family + 4</TT> is a legitimate way of accessing the data at <TT>Family[4]</TT>.</P><P>The compiler does all the arithmetic when you add to, increment, and decrementpointers. The address accessed when you write <TT>Family + 4</TT> isn't 4 bytes pastthe address of <TT>Family</TT>--it is four objects. If each object is 4 bytes long,<TT>Family + 4</TT> is 16 bytes. If each object is a <TT>CAT</TT> that has four <TT>long</TT>member variables of 4 bytes each and two <TT>short</TT> member variables of 2 byteseach, each <TT>CAT</TT> is 20 bytes, and <TT>Family + 4</TT> is 80 bytes past thestart of the array.</P><P>Listing 11.7 illustrates declaring and using an array on the free store.</P><P><A NAME="Heading34"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 11.7. Creatingan array by using new.</B></FONT></P><PRE><FONT COLOR="#0066FF">1: // Listing 11.7 - An array on the free store2:3: #include <iostream.h>4:5: class CAT6: {7: public:8: CAT() { itsAge = 1; itsWeight=5; } 9: ~CAT(); 10: int GetAge() const { return itsAge; }11: int GetWeight() const { return itsWeight; }12: void SetAge(int age) { itsAge = age; }13:14: private:15: int itsAge;16: int itsWeight;17: };18:19: CAT :: ~CAT()20: {21: // cout << "Destructor called!\n";22: }23:24: int main()25: {26: CAT * Family = new CAT[500];27: int i;28: CAT * pCat;29: for (i = 0; i < 500; i++)30: {31: pCat = new CAT;32: pCat->SetAge(2*i +1);33: Family[i] = *pCat;34: delete pCat;35: }36:37: for (i = 0; i < 500; i++)38: {38: cout << "Cat #" << i+1 << ": ";39: cout << Family[i].GetAge() << endl;40: }41:42: delete [] Family;43:44: return 0;<TT>45: }</TT></FONT><FONT COLOR="#0066FF">Output: Cat #1: 1Cat #2: 3Cat #3: 5...Cat #499: 997Cat #500: 999</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Line 26 declares the array<TT>Family</TT>, which holds 500 <TT>CAT</TT> objects. The entire array is createdon the free store with the call to <TT>new</TT> <TT>CAT[500]</TT>.<BR><BR>Each <TT>CAT</TT> object added to the array also is created on the free store (line31). Note, however, that the pointer isn't added to the array this time; the objectitself is. This array isn't an array of pointers to <TT>CAT</TT>s. It is an arrayof <TT>CAT</TT>s.<H3 ALIGN="CENTER"><A NAME="Heading36"></A><FONT COLOR="#000077">Deleting Arrayson the Free Store</FONT></H3><P><TT>Family</TT> is a pointer, a pointer to the array on the free store. When,on line 33, the pointer <TT>pCat</TT> is dereferenced, the <TT>CAT</TT> object itselfis stored in the array (why not? the array is on the free store). But <TT>pCat</TT>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -