Cinda Heeren / Geoffrey Tien Linked Memory Pointers Linked Lists September 21, 2017 Cinda Heeren / Geoffrey Tien
Releasing Dynamic Memory When a function call is complete its stack memory is released and can be re-used Dynamic memory should also be released Failing to do so results in a memory leak It is sometimes not easy to determine when dynamic memory should be released Data might be referred to by more than one pointer Memory should only be released when it is no longer referenced by any pointer Rule of thumb: if you new something, you should delete it (eventually) September 21, 2017 Cinda Heeren / Geoffrey Tien
Stack memory VS heap memory fast access allocation/deallocation and space automatically managed memory will not become fragmented local variables only limit on stack size (OS-dependent) variables cannot be resized Heap variables accessible outside declaration scope no (practical) limit on memory size variables can be resized (relatively) slower access no guaranteed efficient use of space memory management is programmer's responsibility September 21, 2017 Cinda Heeren / Geoffrey Tien
Addresses and pointers Every storage location in memory (RAM) has an address associated with it The address is the location in memory where a given variable or identifier stores its data Can think of address in memory like a mailbox number Use the address to find where the mailbox is Look inside the mailbox to access the contents/value A pointer is a special type of variable That stores an address rather than a value The address is used to find a value elsewhere in memory September 21, 2017 Cinda Heeren / Geoffrey Tien
Cinda Heeren / Geoffrey Tien Declaring pointers Pointer variables are declared as follows: datatype* identifier e.g. int* ptr; or int * ptr; or int *ptr; Note that the type of a pointer is not the same as the type it points to e.g. ptr is a pointer to an int, but is itself not an int Warning! The declaration int* var1, var2; declares var1 as a pointer, but var2 as an integer! To declare both as pointers, either declare individually, or: int *var1, *var2; September 21, 2017 Cinda Heeren / Geoffrey Tien
Address operator and dereferencing Pointers can be assigned the address of an existing variable Using the address operator, & The value which a pointer points to can be accessed by dereferencing the pointer Using the * operator p x … 4096 … 47 23 38 1 212 220-1 int x = 23; int* p = &x; x = 47; *p = 38; September 21, 2017 Cinda Heeren / Geoffrey Tien
Pointers as parameters Passing pointer parameters allows the function to access and/or modify the actual parameter int getArraySum(int arr[], int size, int* pcount) { int sum = 0; for (int i = 0; i < size; i++) { if (arr[i] > 0) (*pcount)++; sum += arr[i]; } return sum; int numpositive = 0; int numbers[] = {3, 7, -9, 5, -4}; int result = getArraySum(numbers, 5, &numpositive); cout << "Array sum: " << result << endl; cout << "Number of positive elements: " << numpositive << endl; September 21, 2017 Cinda Heeren / Geoffrey Tien
Pointers as parameters Another example void f1(int arg) { arg = 22; printf("f1 arg: %d\n", arg); } int x = 45; f1(x); printf("x after f1: %d\n", x); f2(&x); printf("x after f2: %d\n", x); void f2(int* arg) { *arg = 410; printf("f2 arg: %d\n", arg); } September 21, 2017 Cinda Heeren / Geoffrey Tien
Pointer to a pointer ...to a pointer to a pointer... int main() { int x = 5; int* p = &x; *p = 6; int** q = &p; int*** r = &q; cout << "*p: " << *p << endl; cout << "*q: " << *q << endl; cout << "**q: " << *(*q) << endl; } "You can keep adding levels of pointers until your brain explodes or the compiler melts – whichever happens soonest" stackoverflow user JeremyP September 21, 2017 Cinda Heeren / Geoffrey Tien
Pointers and dynamic memory The new keyword allocates space in dynamic memory and returns the first address of the allocated space delete releases the memory at the address referenced by its pointer variable delete[] is used to release memory allocated to array variables int a = 5; int* b = new int; int* c = &a; *c = 4; int** d = &b; int* e = new int[a]; **d = 3; int* f = new int[*b]; delete b; delete e; // causes a memory leak delete[] f; September 21, 2017 Cinda Heeren / Geoffrey Tien
Dynamic allocation of a 2D array int dim_row = 3; int dim_col = 5; int** myarray; // pointer to a pointer stack heap myarray September 21, 2017 Cinda Heeren / Geoffrey Tien
Cinda Heeren / Geoffrey Tien Linked Lists September 21, 2017 Cinda Heeren / Geoffrey Tien
Cinda Heeren / Geoffrey Tien Linked lists A motivation Imagine an array partially filled with data And we want to insert an item in a particular position in the middle 17 12 15 16 19 22 28 34 37 41 46 All of these elements must be shifted over one at a time Linked lists are a dynamic data structure that can achieve fast insertions/ deletions in the middle September 21, 2017 Cinda Heeren / Geoffrey Tien
Cinda Heeren / Geoffrey Tien Linked list nodes A linked list is a dynamic data structure that consists of nodes linked together A node is a data structure that contains data the location of the next node September 21, 2017 Cinda Heeren / Geoffrey Tien
Cinda Heeren / Geoffrey Tien Node pointers A node contains the address of the next node in the list In C++ this is recorded as a pointer to a node Nodes are created in dynamic memory And their memory locations are not in sequence The data attribute of a node varies depending on what the node is intended to store September 21, 2017 Cinda Heeren / Geoffrey Tien
Cinda Heeren / Geoffrey Tien Linked lists A linked list is a chain of nodes where each node stores the address of the next node Start 7 2 6 8 This symbol indicates a null pointer September 21, 2017 Cinda Heeren / Geoffrey Tien
Linked list implementation Node class class Node { public: int data; Node* next; }; next points to another node, hence its type Node* attributes / members of a particular node can be accessed using the '.' (dot) operator or the '->' (arrow) operator as a shorthand for pointer types equivalent to dereferencing and using dot operator Node nd; nd.data = 5; Node* p = nd.next; (*p).data = 5; Node* q = *((*p).next).next; Node* r = q->next->next; September 21, 2017 Cinda Heeren / Geoffrey Tien
Cinda Heeren / Geoffrey Tien Building a linked list Assume we have written a parameterized constructor for the Node class Node* a = new Node(7, null); a 7 September 21, 2017 Cinda Heeren / Geoffrey Tien
Cinda Heeren / Geoffrey Tien Building a linked list Node* a = new Node(7, null); a->next = new Node(3, null); a 7 3 September 21, 2017 Cinda Heeren / Geoffrey Tien
Traversing a linked list Node* a = new Node(7, null); a->next = new Node(3, null); Node* p = a; p = p->next; // go to next node p = p->next; a 7 3 p September 21, 2017 Cinda Heeren / Geoffrey Tien
Cinda Heeren / Geoffrey Tien Linked list insertion Insertion in a singly-linked list requires only updating the next node reference of the preceding position a 15 16 19 22 28 … p 17 b Now think about how we might use a linked list as the data structure for implementing the Stack ADT Node* b = new Node(17, p->next); p->next = b; September 21, 2017 Cinda Heeren / Geoffrey Tien
Cinda Heeren / Geoffrey Tien Linked list removal Likewise, we can remove a node by updating the pointer of the preceding node but remember to delete the removed node! a 15 16 19 22 28 … p b p->next = b->next; delete b; September 21, 2017 Cinda Heeren / Geoffrey Tien
Readings for this lesson Koffman Chapters P.5, 4.5 Next class: Koffman Chapter 5 (ADT Stack) September 21, 2017 Cinda Heeren / Geoffrey Tien