📄 ch08.htm
字号:
stray pointer.<BR>This is a particularly nasty bug, because the value that changed wasn't associatedwith the stray pointer. The change to the value at <TT>pLong</TT> was a side effectof the misuse of <TT>pInt</TT>. In a large program, this would be very difficultto track down. <BR><BR>Just for fun, here are the details of how 65,556 got into that memory address:<DL> <DD><B>1.</B> <TT>pInt</TT> was pointed at a particular memory location, and the value <TT>10</TT> was assigned.<BR> <BR> <B>2.</B> <TT>delete</TT> was called on <TT>pInt</TT>, which told the compiler that it could put something else at that location. Then <TT>pLong</TT> was assigned the same memory location.<BR> <BR> <B>3.</B> The value <TT>90000</TT> was assigned to <TT>*pLong</TT>. The particular computer used in this example stored the four-byte value of 90,000 (00 01 5F 90) in byte-swapped order. Therefore, it was stored as 5F 90 00 01.<BR> <BR> <B>4.</B> <TT>pInt</TT> was assigned the value <TT>20</TT>--or 00 14 in hexadecimal notation. Because <TT>pInt</TT> still pointed to the same address, the first two bytes of <TT>pLong</TT> were overwritten, leaving 00 14 00 01.<BR> <BR> <B>5.</B> The value at <TT>pLong</TT> was printed, reversing the bytes back to their correct order of 00 01 00 14, which was translated into the DOS value of <TT>65556</TT>.<BR> <BR> <HR><B>DO</B> use <TT>new</TT> to create objects on the free store.<B> DO</B> use <TT>delete</TT> to destroy objects on the free store and to return their memory. <B>DON'T</B> forget to balance all <TT>new</TT> statements with a <TT>delete</TT> statement. <B>DON'T</B> forget to assign <TT>null</TT> (<TT>0</TT>) to all pointers that you call <TT>delete</TT> on. <B>DO</B> check the value returned by <TT>new</TT>. <HR></DL><H3 ALIGN="CENTER"><A NAME="Heading42"></A><FONT COLOR="#000077">const Pointers</FONT></H3><P>You can use the keyword <TT>const</TT> for pointers before the type, after thetype, or in both places. For example, all of the following are legal declarations:</P><PRE><FONT COLOR="#0066FF">const int * pOne;int * const pTwo;const int * const pThree;</FONT></PRE><P><TT>pOne</TT> is a pointer to a constant integer. The value that is pointed tocan't be changed.</P><P><TT>pTwo</TT> is a constant pointer to an integer. The integer can be changed,but <TT>pTwo</TT> can't point to anything else.</P><P><TT>pThree</TT> is a constant pointer to a constant integer. The value that ispointed to can't be changed, and <TT>pThree</TT> can't be changed to point to anythingelse.</P><P>The trick to keeping this straight is to look to the right of the keyword <TT>const</TT>to find out what is being declared constant. If the type is to the right of the keyword,it is the value that is constant. If the variable is to the right of the keyword<TT>const</TT>, it is the pointer variable itself that is constant.</P><PRE><FONT COLOR="#0066FF">const int * p1; // the int pointed to is constantint * const p2; // p2 is constant, it can't point to anything else</FONT></PRE><H4 ALIGN="CENTER"><A NAME="Heading43"></A><FONT COLOR="#000077">const Pointers andconst Member Functions</FONT></H4><P>On Day 6, "Basic Classes," you learned that you can apply the keyword<TT>const</TT> to a member function. When a function is declared <TT>const</TT>,the compiler flags as an error any attempt to change data in the object from withinthat function.</P><P>If you declare a pointer to a <TT>const</TT> object, the only methods that youcan call with that pointer are <TT>const</TT> methods. Listing 8.10 illustrates this.</P><P><A NAME="Heading44"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 8.10. Usingpointers to const objects.</B></FONT></P><PRE><FONT COLOR="#0066FF">1: // Listing 8.102: // Using pointers with const methods3:4: #include <iostream.h>5:6: class Rectangle7: {8: public:9: Rectangle();10: ~Rectangle();11: void SetLength(int length) { itsLength = length; }12: int GetLength() const { return itsLength; }13:14: void SetWidth(int width) { itsWidth = width; }15: int GetWidth() const { return itsWidth; }16:17: private:18: int itsLength;19: int itsWidth;20: };21:22: Rectangle::Rectangle():23: itsWidth(5),24: itsLength(10)25: {}26:27: Rectangle::~Rectangle()28: {}29:30: int main()31: {32: Rectangle* pRect = new Rectangle;33: const Rectangle * pConstRect = new Rectangle;34: Rectangle * const pConstPtr = new Rectangle;35:36: cout << "pRect width: " << pRect->GetWidth() << " feet\n";37: cout << "pConstRect width: " << pConstRect->GetWidth() << " feet\n";38: cout << "pConstPtr width: " << pConstPtr->GetWidth() << " feet\n";39:40: pRect->SetWidth(10);41: // pConstRect->SetWidth(10);42: pConstPtr->SetWidth(10);43:44: cout << "pRect width: " << pRect->GetWidth() << " feet\n";45: cout << "pConstRect width: " << pConstRect->GetWidth() << " feet\n";46: cout << "pConstPtr width: " << pConstPtr->GetWidth() << " feet\n";47: return 0;<TT>48: }</TT></FONT><FONT COLOR="#0066FF">Output: pRect width: 5 feetpConstRect width: 5 feetpConstPtr width: 5 feetpRect width: 10 feetpConstRect width: 5 feetpConstPtr width: 10 feet</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis: </B></FONT>Lines 6-20 declare <TT>Rectangle</TT>.Line 15 declares the <TT>GetWidth()</TT> member method <TT>const</TT>. Line 32 declaresa pointer to <TT>Rectangle</TT>. Line 33 declares <TT>pConstRect</TT>, which is apointer to a constant <TT>Rectangle</TT>. Line 34 declares <TT>pConstPtr</TT>, whichis a constant pointer to <TT>Rectangle</TT>.<BR>Lines 36-38 print their values.</P><P>In line 40, <TT>pRect</TT> is used to set the width of the rectangle to <TT>10</TT>.In line 41, <TT>pConstRect</TT> would be used, but it was declared to point to aconstant <TT>Rectangle</TT>. Therefore, it cannot legally call a non-<TT>const</TT>member function; it is commented out. In line 38, <TT>pConstPtr</TT> calls <TT>SetAge()</TT>.<TT>pConstPtr</TT> is declared to be a constant pointer to a rectangle. In otherwords, the pointer is constant and cannot point to anything else, but the rectangleis not constant.<H4 ALIGN="CENTER"><A NAME="Heading46"></A><FONT COLOR="#000077">const this Pointers</FONT></H4><P>When you declare an object to be <TT>const</TT>, you are in effect declaring thatthe <TT>this</TT> pointer is a pointer to a <TT>const</TT> object. A <TT>const</TT><TT>this</TT> pointer can be used only with <TT>const</TT> mem- ber functions.</P><P>Constant objects and constant pointers will be discussed again tomorrow, whenreferences to constant objects are discussed.<BLOCKQUOTE> <P><HR><B>DO</B> protect objects passed by reference with <TT>const</TT> if they should not be changed. <B>DO </B>pass by reference when the object can be changed.<B> DO</B> pass by value when small objects should not be changed. <HR></BLOCKQUOTE><H3 ALIGN="CENTER"><A NAME="Heading47"></A><FONT COLOR="#000077">Summary</FONT></H3><P>Pointers provide a powerful way to access data by indirection. Every variablehas an address, which can be obtained using the <TT>address of</TT> operator (<TT>&</TT>).The address can be stored in a pointer.</P><P>Pointers are declared by writing the type of object that they point to, followedby the indirection operator (<TT>*</TT>) and the name of the pointer. Pointers shouldbe initialized to point to an object or to <TT>null</TT> (<TT>0</TT>).</P><P>You access the value at the address stored in a pointer by using the indirectionoperator (<TT>*</TT>). You can declare <TT>const</TT> pointers, which can't be reassignedto point to other objects, and pointers to <TT>const</TT> objects, which can't beused to change the objects to which they point.</P><P>To create new objects on the free store, you use the <TT>new</TT> keyword andassign the address that is returned to a pointer. You free that memory by callingthe <TT>delete</TT> keyword on the pointer. <TT>delete</TT> frees the memory, butit doesn't destroy the pointer. Therefore, you must reassign the pointer after itsmemory has been freed.<H3 ALIGN="CENTER"><A NAME="Heading48"></A><FONT COLOR="#000077">Q&A</FONT></H3><DL> <DD><B>Q. Why are pointers so important?<BR> </B><BR> <B>A.</B> Today you saw how pointers are used to hold the address of objects on the free store and how they are used to pass arguments by reference. In addition, on Day 13, "Polymorphism," you'll see how pointers are used in class polymorphism.<BR> <BR> <B>Q. Why should I bother to declare anything on the free store?<BR> </B><BR> <B>A.</B> Objects on the free store persist after the return of a function. Additionally, the ability to store objects on the free store enables you to decide at runtime how many objects you need, instead of having to declare this in advance. This is explored in greater depth tomorrow.<BR> <BR> <B>Q. Why should I declare an object const if it limits what I can do with it?<BR> </B><BR> <B>A.</B> As a programmer, you want to enlist the compiler in helping you find bugs. One serious bug that is difficult to find is a function that changes an object in ways that aren't obvious to the calling function. Declaring an object <TT>const</TT> prevents such changes.</DL><H3 ALIGN="CENTER"><A NAME="Heading49"></A><FONT COLOR="#000077">Workshop</FONT></H3><P>The Workshop provides quiz questions to help you solidify your understanding ofthe material covered and exercises to provide you with experience in using what you'velearned. Try to answer the quiz and exercise questions before checking the answersin Appendix D, and make sure you understand the answers before continuing to thenext chapter.<H4 ALIGN="CENTER"><A NAME="Heading50"></A><FONT COLOR="#000077">Quiz</FONT></H4><DL> <DD><B>1.</B> What operator is used to determine the address of a variable?<BR> <BR> <B>2.</B> What operator is used to find the value stored at an address held in a pointer?<BR> <BR> <B>3.</B> What is a pointer?<BR> <BR> <B>4.</B> What is the difference between the address stored in a pointer and the value at that address?<BR> <BR> <B>5.</B> What is the difference between the indirection operator and the <TT>address of</TT> operator?<BR> <BR> <B>6.</B> What is the difference between <TT>const int * ptrOne</TT> and <TT>int * const ptrTwo</TT>?</DL><H4 ALIGN="CENTER"><A NAME="Heading51"></A><FONT COLOR="#000077">Exercises</FONT></H4><DL> <DD><B>1.</B> What do these declarations do? <DL> <DD><B><BR> a.</B> <TT>int * pOne;</TT> </DL> <DD> <DL> <DD><B>b.</B> <TT>int vTwo;</TT> </DL> <DD> <DL> <DD><B>c.</B> <TT>int * pThree = &vTwo;</TT> </DL> <DD><BR> <B>2.</B> If you have an <TT>unsigned short</TT> variable named <TT>yourAge</TT>, how would you declare a pointer to manipulate <TT>yourAge</TT>?<BR> <BR> <B>3.</B> Assign the value <TT>50</TT> to the variable <TT>yourAge</TT> by using the pointer that you declared in Exercise 2.<BR> <BR> <B>4.</B> Write a small program that declares an integer and a pointer to integer. Assign the address of the integer to the pointer. Use the pointer to set a value in the integer variable.<BR> <BR> <B>5.</B> BUG BUSTERS: What is wrong with this code?</DL><PRE><FONT COLOR="#0066FF">#include <iostream.h>int main(){ int *pInt; *pInt = 9; cout << "The value at pInt: " << *pInt; return 0;}</FONT></PRE><DL> <DD><B>6.</B> BUG BUSTERS: What is wrong with this code?</DL><PRE><FONT COLOR="#0066FF">int main(){ int SomeVariable = 5; cout << "SomeVariable: " << SomeVariable << "\n"; int *pVar = & SomeVariable; pVar = 9; cout << "SomeVariable: " << *pVar << "\n";return 0;}</FONT></PRE><
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -