610 likes | 786 Vues
Dynamic Structures & Arrays. What is a pointer variable?. A pointer variable is a variable whose value is the address of a location in memory . To declare a pointer variable, you must specify the type of value that the pointer will point to. For example,
E N D
Dynamic Structures & Arrays
What is a pointer variable? A pointer variable is a variable whose value is the address of a location in memory. To declare a pointer variable, you must specify the type of value that the pointer will point to. For example, int* ptr;// ptr will hold the address of an int char* q;// q will hold the address of a char
Using a pointer variable int x; x = 12; int* ptr; ptr = &x; NOTE: Because ptr holds the address of x, we say that ptr“points to”x 2000 12 x 3000 2000 ptr
Unary operator * is the deference (indirection) operator int x; x = 12; int* ptr; ptr = &x; std::cout << *ptr; NOTE: The value pointed to by ptr is denoted by *ptr 2000 12 x 3000 2000 ptr
Using the dereference operator int x; x = 12; int* ptr; ptr = &x; *ptr = 5; // changes the value // at adddressptr to 5 2000 12 x 3000 2000 ptr 5
Another Example 4000 A ch 5000 4000 q char ch; ch = ‘A’; char* q; q = &ch; *q = ‘Z’; char* p; p = q; // the right side has value 4000 // now p and q both point to ch Z 6000 4000 p
Dynamically Allocated Data char* ptr; ptr = new char; *ptr = ‘B’; std::cout << *ptr; 2000 ptr New is an operator
Dynamically Allocated Data char* ptr; ptr = new char; *ptr = ‘B’; std::cout << *ptr; NOTE: Dynamic data has no variable name 2000 ptr
Dynamically Allocated Data char* ptr; ptr = new char; *ptr = ‘B’; std::cout << *ptr; 2000 ptr ‘B’
Dynamically Allocated Data char* ptr; ptr = new char; *ptr = ‘B’; std::cout << *ptr; delete ptr; 2000 ptr NOTE: Delete deallocates the memory pointed to by ptr. ?
what does new do? • takes a pointer variable, • allocates memory for it to point, and • leaves the address of the assigned memory in the pointer variable. • If there is no more memory, the pointer variable is set to NULL.
The NULL Pointer There is a pointer constant called NULL available in cstddef. NULL is not a memory address; it means that the pointer variable points to nothing. It is an error to dereference a pointer whose value is NULL. It is the programmer’s job to check for this. while (ptr != NULL) { . . .// ok to use *ptr here }
int* ptr = new int; *ptr = 3; ptr = new int; // changes value of ptr *ptr = 4; What happens here? 3 ptr 3 ptr 4
Memory Leak A memory leak occurs when dynamic memory (that was created using operator new) has been left without a pointer to it by the programmer, and so is inaccessible. int* ptr = new int; *ptr = 8; int* ptr2 = new int; *ptr2 = -5; 8 ptr -5 ptr2 How else can an object become inaccessible?
Causing a Memory Leak int* ptr = new int; *ptr = 8; int* ptr2 = new int; *ptr2 = -5; ptr = ptr2; // here the 8 becomes inaccessible 8 ptr -5 ptr2 8 ptr -5 ptr2
The object or array currently pointed to by the pointer is deallocated, and the pointer is considered unassigned. The memory is returned to the free store. Square brackets are used with delete to deallocate a dynamically allocated array of classes. Using operator delete
occurs when two pointers point to the same object and delete is applied to one of them. int* ptr = new int; *ptr = 8; int* ptr2 = new int; *ptr2 = -5; ptr= ptr2; A Dangling Pointer 8 ptr -5 ptr2
int* ptr = new int; *ptr = 8; int* ptr2 = new int; *ptr2 = -5; ptr = ptr2; delete ptr2; // ptr is left dangling ptr2 = NULL; Leaving a Dangling Pointer 8 ptr -5 ptr2 8 ptr NULL ptr2
Remember? • A list is a homogeneous collection of elements, with a linear relationship between elements. • Each list element (except the first) has a unique predecessor, and • each element (except the last) has a unique successor.
change state observe state process all ADT Unsorted List Operations Transformers • MakeEmpty • PutItem • DeleteItem Observers • IsFull • GetLength • GetItem Iterators • ResetList • GetNextItem
struct NodeType; #include “ItemType.h”// unsorted.h . . . class UnsortedType { public : // LINKED LIST IMPLEMENTATION // The public interface is the same private : // The private part is different NodeType<ItemType>* listData; int length; NodeType<ItemType>* currentPos; }; struct NodeType { ItemType info; NodeType* next; } ; Do we have to keep a length field? Do we need an IsFull?
‘X’‘C’‘L’ class UnsortedType<char> UnsortedType Private data: length 3 listData currentPos ? MakeEmpty ~UnsortedType GetItem PutItem DeleteItem . . . GetNextItem
// LINKED LIST IMPLEMENTATION ( unsorted.cpp ) #include “itemtype.h” UnsortedType::UnsortedType ( ) // constructor // Pre: None. // Post: List is empty. { length = 0; listData = NULL; } int UnsortedType::GetLength( ) const // Post: Function value = number of items in the list. { return length; } 24
ItemType UnsortedType::GetItem( ItemType item, bool& found ) // Pre: Key member of item is initialized. // Post: If found, item’s key matches an element’s key in the list // a copy of that element is returned; otherwise, // original item is returned. { bool moreToSearch; NodeType<ItemType>* location; location = listData; found = false ; moreToSearch = ( location != NULL ); while ( moreToSearch && !found ) { if ( item == location->info ) // match here { found = true; item = location->info; } else // advance pointer { location = location->next; moreToSearch = ( location != NULL ); } } return item; } 25
void UnsortedType::PutItem ( ItemType item ) // Pre: list is not full and item is not in list. // Post: item is in the list; length has been incremented. { NodeType<ItemType>* location; // obtain and fill a node location = new NodeType<ItemType>; location->info = item; location->next = listData; listData = location; length++; } 26
‘X’‘C’‘L’ Inserting ‘B’ into an Unsorted List Private data: length 3 listData currentPos ?
‘X’‘C’‘L’ location = new NodeType; item location ‘B’ Private data: length 3 listData currentPos ?
‘X’‘C’‘L’ location->info = item ; • item • location ‘B’ ‘B’ Private data: length 3 listData currentPos ?
‘X’‘C’‘L’ location->next = listData ; ‘B’ • item • location ‘B’ Private data: length 3 listData currentPos ?
‘X’‘C’‘L’ listData = location ; • item • location ‘B’ ‘B’ Private data: length 3 listData currentPos ?
‘X’‘C’‘L’ length++ ; • item • location ‘B’ ‘B’ Private data: length 4 listData currentPos ?
One-Dimensional Array at the Logical Level A one-dimensional array is a structured composite data type made up of a finite, fixed size (known at compile time) collection of homogeneous (all of the same data type) elements having relative positions and to which there is direct access (any element can be accessed immediately). Array operations (creation, storing a value, retrieving a value) are performed using a declaration and indexes.
Implementation Example This ACCESSING FUNCTION gives position of name[Index] Address(Index) = BaseAddress + Index * SizeOfElement char name[10]; // assume element size is 1 byte Base Address 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 name[0] name[1] name[2] name[3] name[4] . . . . . name[9]
Another Example This ACCESSING FUNCTION gives position of values[Index] Address(Index) = BaseAddress + Index * SizeOfElement float values[5]; // assume element size is 4 bytes Base Address 7000 7004 7008 7012 7016 values[0] values[1] values[2] values[3] values[4] Indexes
One-Dimensional Arrays in C++ • The index must be of an integral type • char, short, int, long, or enum • The index range is always 0 through the array size minus 1 • Arrays cannot be assigned one to another, • and cannot be the return type of a function
Passing Arrays as Parameters • In C++, arrays are always passed by reference, • and &is not used with the formal parameter type. • Whenever an array is passed as a parameter, its base address is sent to the called function.
float SumValues (const float values[ ], numOfValues) // Pre: values[ 0] through values[numOfValues-1] // have been assigned // Returns the sum of values[0] through // values[numOfValues-1] { float sum = 0; for ( int index = 0; index < numOfValues; index++ ) { sum = values [index] + sum; } return sum; }
Two-Dimensional Array at the Logical Level A two-dimensional array is a structured composite data type made up of a finite, fixed size collection of homogeneous elements having relative positions and to which there is direct access. Array operations (creation, storing a value, retrieving a value) are performed using a declaration and a pair of indexes (called row and column) representing the component’s position in each dimension.
EXAMPLE -- To keep monthly high temperatures for 50 states in a two-dimensional array. constint NUM_STATES = 50 ; constint NUM_MONTHS = 12 ; intstateHighs [ NUM_STATES ] [ NUM_MONTHS ] ; [ 0 ] [ 1 ] [ 2 ] . . stateHighs [2] [7] . [ 48 ] [ 49 ] [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] 66 64 72 78 85 90 99 115 98 90 88 80 row 2, col 7 might be Arizona’s high for August
Finding the average high temperature for Arizona float total = 0; int month; float average; for ( month = 0; month < NUM_MONTHS; month ++ ) total = total + stateHighs [ 2 ][ month ]; average = ( total / NUM_MONTHS);
const int NUM_STATES = 50 ;const int NUM_MONTHS = 12 ;int stateHighs [ NUM_STATES ] [ NUM_MONTHS ] ; rows columns STORAGE • In memory, C++ stores arrays in row order. The first row is followed by the second row, etc. Base Address 8000 8024 8048 . . . 12 highs for state 0 12 highs for state 1 etc. Alabama Alaska first row second row
Implementation Level View stateHighs[ 0 ] [ 0 ] stateHighs[ 0 ] [ 1 ] stateHighs[ 0 ] [ 2 ] stateHighs[ 0 ] [ 3 ] stateHighs[ 0 ] [ 4 ] stateHighs[ 0 ] [ 5 ] stateHighs[ 0 ] [ 6 ] stateHighs[ 0 ] [ 7 ] stateHighs[ 0 ] [ 8 ] stateHighs[ 0 ] [ 9 ] stateHighs[ 0 ] [10 ] stateHighs[ 0 ] [11 ] stateHighs[ 1 ] [ 0 ] stateHighs[ 1 ] [ 1 ] stateHighs[ 1 ] [ 2 ] stateHighs[ 1 ] [ 3 ] . . . Base Address 8000 To locate an element such as stateHighs [ 2 ] [ 7] the compiler needs to know that there are 12 columns in this two-dimensional array. At what address will stateHighs [ 2 ] [ 7 ] be found? Assume 2 bytes for type int.
Two-Dimensional Array Parameters • Just as with a one-dimensional array, when a two- (or higher) dimensional array is passed as a parameter, the base address of the actual array is sent to the function. • The size of all dimensions except the first must be included in the function heading and prototype. • The sizes of those dimensions for the formal parameter must be exactly the same as in the actual array.
Use the two-dimensional stateHighs array to fill a one-dimensional stateAverages array constint NUM_STATES = 50 ; constint NUM_MONTHS = 12 ; intstateHighs [ NUM_STATES ] [ NUM_MONTHS ] ; float stateAverages [ NUM_STATES ] ; [ 0 ] ? [ 1 ] ? [ 2 ] . . . [ 48 ] [ 49 ] [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] Alaska Arizona 43 42 50 55 60 78 79 80 77 72 63 40 66 64 72 78 85 90 99 115 98 90 88 80
void findAverages(constintstateHighs[NUM_STATES] [NUM_MONTHS], intstateAverages[NUM_STATES]) // Pre: stateHighs[ 0..NUM_STATES-1] [ 0..NUM_MONTHS-1] // assigned // Post: stateAverages[ 0..NUM_STATES-1 ] contains rounded // high temperature for each state { int state; int month; float total; for ( state = 0 ; state < NUM_STATES; state++ ) { total = 0.0; for ( month = 0 ; month < NUM_MONTHS ; month++ ) total = stateHighs [ state ][ month ] + total; stateAverages [ state ] = total / NUM_MONTHS; } }