740 likes | 831 Views
Pointers. (Walls & Mirrors - Beginning of Chapter 4). What’s a Pointer?. A pointer variable is a variable that can contain the location of another variable as its value. The location of a variable is usually implemented by indicating its address in (RAM) memory.
E N D
Pointers (Walls & Mirrors - Beginning of Chapter 4)
What’s a Pointer? • A pointer variable is a variable that can contain the location of another variable as its value. • The location of a variable is usually implemented by indicating its address in (RAM) memory. • The location (or address) of a variable is called a pointer. • Sometimes, for brevity, a pointer variable is simply called a pointer. You will need to be careful to understand whether pointer refers to a variable or the address of a variable.
Pointers -“Real Life” Examples • Suppose that your friend, Sam, borrows your copy of Walls & Mirrors. In its place, he leaves you the note Borrowed your Walls & Mirrors book. Thanks, Sam • This note is like a pointer, since it it not your book, but it tells you where to go to find it. (The paper on which the note is written is like a pointer variable.)
Pointer variable Other variable Pointers - Graphical Representation • A variable is often represented as a box. • The value of the variable is written inside the box. • If the variable is a pointer variable, containing a pointer, the box will contain the “tail” of an arrow that points to another variable.
Pointers - Suggestion • If you have a problem with pointers, draw the layout. • It may be difficult to understand what is going on without a graphical representation of the pointer relationships.
Pointer Declarations int *iptr; // iptr is a pointer to an int char *cptr; // cptr is a pointer to a char float *fptr; // fptr is a pointer to a float List *Lptr; // Lptr is a pointer to a List object Sphere *Sptr; // Sptr is a pointer to a Sphere object
Pointer Operations • Assignment: = • A pointer variable can be assigned only a pointer (i.e. the address of a variable) or NULL (which equals 0). • Comparison: = =, != • Pointers can be compared for equality. • Addition/Subtraction: +, • Pointers can be incremented or decremented with an integer. • Dereferencing: * • *ptr returns the value of the object pointed to by ptr. • Address of: & • &ptr returns the address of ptr (i.e. pointer to ptr).
Pointer Operations - Address of • The Address of operator & returns the address of an object. float PI = 3.14159; float *PIptr; &PI returns the address of the variable PI,not 3.14159 (the value stored in PI). PIptr = &PI stores the address of variable PI in variable, PIptr. &PIptr returns the address of variable PIptr.
Pointer Operations - Dereferencing • The Dereferencing operator * returns the value of the object to which its operand points. float PI = 3.14159; float *PIptr; float X; PIptr = Π // PIptr contains the address of PI X = *PIptr; // Value stored in PI (3.14159) is // assigned to X *(*(&PIptr)) = *PIptr = *(&PI) = PI = 3.14159
Pointer Initialization int *ptr; // pointer to int declared, value undefined int x = 5; // int declared and initialized to 5 cout << x; // prints 5 cout << *ptr; // Error! Prints undefined value, since ptr not // initialized ptr = &x; // ptr now contains the address of x cout << *ptr; // prints 5
Pointer Initialization - Suggestion • When a pointer variable is declared it is (by default) uninitialized. Therefore, where it is pointing is undefined. • It’s a good practice to initialize newly declared pointer variables to the NULL pointer (= 0). • This will insure that the pointer variable is not pointing anywhere it shouldn’t. • This will help you determine if a valid pointer has been assigned to it. if( ptr = = NULL ) cout << “ptr has not been initialized” << endl;
ptr new int variable new Operator • The operator new creates a new object of a given type. • new returns a pointer to the newly created object. ptr = new int;
new Operator (Cont’d.) • An object created with new does not have a name and is not declared. • An object created with new can only be used by following (dereferencing) a pointer to it. • You need to be careful to not lose the pointer to an object created with new, since there is no other way to access it. • Memory that was allocated with new and has become inaccessible is called a memory leak. • For programs that run for long periods of time, memory leaks can be the reason for system failure.
new Operator - Example 1 int *ptr; // pointer to int declared, value undefined *ptr = 5; // Error! ptr contains invalid address and // space for int not allocated ptr = new int; // space for int allocated and pointer to it // assigned to ptr *ptr = 5; // 5 is stored in the int pointed to by ptr
new Operator - Example 2 int *p, *q; // declare two pointer to int variables p = new int; // allocate space for an int; make p point to it *p = 25; // store 25 in the int pointed to by p What is the effect of the following? q = p;
p q new int 25 new Operator - Example 2 (Cont’d.) Draw a picture!
new Operator - Example 3 int *p, *q; // declare two pointer to int variables p = new int; // allocate space for an int; make p point to it q = new int; // allocate space for an int; make q point to it *p = 35; // store 35 in the int pointed to by p What is the effect of the following? *q = *p;
p q new int 35 35 new int new Operator - Example 3 (Cont’d.) Draw a picture!
new Operator - Example 3 (Cont’d.) What would have happened if we had executed q = p; instead of *q = *p;
p q new int 35 ? new int new Operator - Example 3 (Cont’d.) The new int, previously pointed to by q is LOST and cannot be recovered. This is called a memory leak.
Arrays and Pointers int a[50]; int *aptr = a; a is equivalent to &a[0] aptr = a; is equivalent to aptr = &a[0]; aptr+5 is equivalent to &a[5] *(aptr+5) is equivalent to a[5]
Linked Lists (Walls & Mirrors - Chapter 4)
Overview • Insert into a Sorted, Linked List • Displaying the Data in a Linked List • Delete from a Sorted, Linked List • Copy Constructor • Saving a Linked List to a File • Circular Linked Lists • Dummy-Headed Linked Lists • Doubly Linked Lists
Definitions • Recall, a list is an ordered collection of elements. • A linked-list is a list in which each element (or node) contains a link (or pointer) to the next element in the list.
Insert into a Sorted, Linked List Steps: 1) Determine where to insert. 2) Create a new node and store the new data in it. 3) Connect the new node into the linked list.
12 27 38 53 NULL 50 head newValue Determine Where to Insert Suppose that we would like to insert 50 into the following, sorted linked list.
struct ListNode { int value; ListNode *next; }; ListNode *head; // assume that a sorted, linked list of // ListNodes has been created ListNode *cur = head; while( newValue > cur -> value ) cur = cur -> next; 12 27 38 53 50 cur head newValue Determine Where to Insert (Cont’d.)
12 27 38 53 head cur 50 newValue Determine Where to Insert (Cont’d.) Searching through the list ends in this configuration. Problem: We can’t insert unless we have a pointer to the node before the position we want to insert.
12 27 38 53 50 head cur prev newValue Determine Where to Insert (Cont’d.) ListNode *prev = NULL; ListNode *cur = head; while( newValue > cur -> value ) { prev = cur; cur = cur -> next; }
Determine Where to Insert (Cont’d.) Problem: If newValue is greater than all the values in the list, then when we get to the last ListNode cur = cur -> next will assign NULL to cur. The subsequent cur -> value will cause program termination, due to an illegal reference.
Determine Where to Insert (Cont’d.) ListNode *prev = NULL; ListNode *cur = head; while( (cur != NULL) && (newValue > cur -> value) ) { prev = cur; cur = cur -> next; } We now have a piece of code that will set prev to the place in the linked list where newValue should be inserted.
Create a New Node & Store the Data Recall that the nodes in our list have been declared as struct ListNode { int value; ListNode *next; }; Consequently, we can create and initialize a new node as follows: ListNode *newNode; newNode = new ListNode; newNode -> value = newValue; newNode -> next = NULL;
12 27 38 53 newNode 50 50 head prev cur newValue Connect the New Node Into the List This is achieved by newNode -> next = cur; prev -> next = newNode; What happens if we try to insert at the end of the list?
12 27 38 53 prev 60 60 head cur newNode newValue Insert at the End of the List newNode -> next = cur; prev -> next = newNode; What if we try to insert at the beginning of the list?
12 27 38 53 prev 4 head 4 cur newNode newValue Insert at the Beginning of the List newNode -> next = cur; prev -> next = newNode; Since prev = NULL, prev -> next is an illegal reference!
12 27 38 53 prev 4 head 4 cur newNode newValue Insert at the Beginning of the List (Cont’d.) else { newNode -> next = head; head = newNode; } if( prev != NULL ) { newNode -> next = cur; prev -> next = newNode; }
Insert into an Empty List What happens if the list is empty to begin with? if( head = = NULL ) { head = new ListNode; head -> value = newValue; head -> next = NULL; }
if( head = = NULL ) { head = new ListNode; head -> value = newValue; head -> next = NULL; } else // search for place to insert { ListNode *prev = NULL; ListNode *cur = head; while( (cur != NULL) && (newValue > cur -> value) ) { prev = cur; cur = cur -> next; } // create a new node ListNode *newNode; newNode = new ListNode; newNode -> value = newValue; // connect it into the list if( prev != NULL ) { newNode -> next = cur; prev -> next = newNode; } else { newNode -> next = head; head = newNode; } } Insert: Putting it All Together
ADT SortedList Operation • How do we turn this code into an operation on an ADT SortedList ? • First, define the public, member-function declaration: void insert( ItemType newValue, bool &success ); should insert newValue into a SortedList at the proper place. Success is true if insertion is successful, otherwise false. • Next, modify the preceding code to • set success appropriately • handle duplicates appropriately • Finally, include the member-function declaration and definition in the following:
Class Definition for the ADT SortedList typedef int ItemType; // items in SortedList are int’s class SortedList { public: // declarations of public member functions private: struct ListNode { ItemType value; ListNode *next; }; ListNode *head; };
Displaying the SortedList Data void SortedList::print( ) { for( ListNode *cur = head; cur != NULL; cur = cur -> next ) cout << cur -> value << endl; }
Delete from a Sorted, Linked List Steps: 1) Locate the node to be deleted. 2) Disconnect the node from the linked list. 3) Make the node available for reuse.
12 27 38 53 head 38 targetValue Locate the Node to be Deleted Suppose that we would like to delete the node containing 38 from the following, sorted linked list.
12 27 38 53 38 head cur prev targetValue Locate the Node to be Deleted (Cont’d.) ListNode *prev = NULL; ListNode *cur = head; while( (cur != NULL) && (targetValue != cur -> value) ) { prev = cur; cur = cur -> next; } What is the value of prev if targetValue is at the head of the list? What is the value of cur if targetValue is not found?
if( cur != NULL ) { if( prev != NULL ) prev -> next = cur -> next; else head = cur -> next; cur -> next = NULL; } 12 27 38 53 38 head cur prev targetValue Disconnect the Node from the List Note: cur points to the node that was disconnected from the list.
12 27 53 38 38 head cur prev targetValue Make the Node Available for Reuse delete cur; // de-allocates the node pointed to by cur, not cur cur = NULL; Although the node pointed to by cur has been returned to the system for reuse, it’s a good idea to set its next pointer and cur to NULL, so that at next use, they are not unintentionally pointing to a valid node.
ADT SortedList Operation • How do we turn the preceding code into an operation on an ADT SortedList ? • First, provide the public, member-function declaration: void remove( ItemType targetValue, bool &success ); should remove targetValue from a SortedList. Success is true if insertion is successful, otherwise false. (Note: since delete is a reserved word, we call this function remove.) • Next, modify the preceding code to set success appropriately. • Finally, include the member-function declaration for remove( ) in the SortedList class declaration, followed by it’s definition.
SortedList Constructor & Destructor SortedList::SortedList( ) : head( NULL ) { } // default constructor SortedList::~SortedList( ) // de-allocate all the nodes { // in the SortedList while( head != NULL ) { ListNode *cur; cur = head -> next; delete head; // de-allocates the node pointed to by head head = cur; } }
SortedList Copy Constructor • Whenever a C++ program • passes an ADT to a function by value, • returns an ADT as the value of a function, or • uses an ADT to initialize an object, a copy constructor is invoked implicitly to make a new copy of the ADT. • If you don’t provide one, the compiler will generate a copy constructor that copies only the data members of the ADT, instead of the complete structure of the ADT (shallow copy).
if( oSortedList.head = = NULL ) head = NULL; else { head = new ListNode; head -> value = oSortedList.head -> value; ListNode *pnew = head; ListNode *porig = oSortedList.head -> next; porig 12 27 38 53 oSortedList.head 12 head pnew SortedList Copy Constructor (Cont’d.)