1.08k likes | 1.32k Views
Pointer: Dynamic Allocation This lecture prepared by the instructors at the University of Manitoba in Canada and has been modified by Dr. Ahmad Reza Hadaegh. Dynamic Allocation - Main memory can be thought of as a (very) large one-dimensional array of memory locations
E N D
Pointer: Dynamic Allocation This lecture prepared by the instructors at the University of Manitoba in Canada and has been modified by Dr. Ahmad Reza Hadaegh
Dynamic Allocation - Main memory can be thought of as a (very) large one-dimensional array of memory locations - Each location holds 1 byte and has its own address - Starts at 0 in increments of 1 - Usually in hexadecimal - 0000 - FFFF represents 64K of memory - 64 * 1024 = 65,536 memory locations 0000 0001 0002 0003 0004 0005 •• FFFF
Dynamic Allocation - When variables are declared they are allocated memory - An integer requires (say) 4 bytes and thus gets 4 consecutive locations in memory - Most machines would store an int in 4 bytes - The address of the integer is the first byte and is effectively stored via the variable name
Dynamic Allocation - An integer variable X would effectively “point” to the starting address of the 4 bytes required - X must be dereferenced in order to be used - Dereference means to interpret what exists at a particular memory location - Dereference is implicit here memory integer variable X
Dynamic Allocation - It is possible to explicitly declare a variable that contains the address of other variables - Creating variables that are pointers
typedef int* intptr; int main ( ) { intptr ptr1; Dynamic Allocation Must be a pointer to a valid C++ type (either built-in or user defined type) intptr is a pointer to an integer •••
Syntax notes: Dynamic Allocation is the same as ... int main ( ) { int* ptr1; int* ptr2; int* ptr3; int main ( ) { int *ptr1, *ptr2, *ptr3; ••• •••
Dynamic Allocation - A pointer in C++ must point to storage of a particular type ptr1 is a pointer to an integer - ptr1 is a 4 byte variable that is able to point to a 4 byte variable - The value of ptr1 is not initialized and is at this point garbage
Dynamic Allocation - To allocate storage for ptr1 to point to: typedef int* intptr; int main ( ) { intptr ptr1; ptr1 = new int; 4 bytes of storage allocated for ptr1 to point to •••
Dynamic Allocation - Unlike “normal” variables, pointers must be explicitly dereferenced *ptr1 = 200; Store 200 in the 4 bytes pointed to by ptr1
Dynamic Allocation - Other manipulation may take place i = *ptr1; Assign 200 to integer variable i
Dynamic Allocation Other manipulation may not sensibly take place i = ptr1; Assign the address that ptr1 points to to integer variable i?
Dynamic Allocation - What happens here? ptr1 only exists once -- as such, each “new” points ptr1 to newly allocated 2 byte area typedef int* intptr; void main () { intptr ptr1; int i; for (i=1;i<=1000;i++) { ptr1 = new int; *ptr1 = 1234; } } The first 999 storage areas are reserved by the OS, but no longer accessible Memory leak! - Memory leaks are common problems in many applications
Dynamic Allocation - Storage that is allocated via “new” should be freed via “delete” during the execution of a program typedef int* intptr; void main () { intptr ptr1; int i; for (i=1;i<=1000;i++) { ptr1 = new int; *ptr1 = 1234; delete ptr1; } } Not really useful, but you get the point
Dynamic Allocation typedef int* intptr; void main () { intptr P, Q; P = new int; *P = 1 Q = new int; *Q = 2; cout << *P << ‘ ’ << *Q << endl; *P = *Q + 3; cout << *P << ‘ ’ << *Q << endl; P = Q; cout << *P << ‘ ’ << *Q << endl; } ? P ? Q •••
Dynamic Allocation typedef int* intptr; void main () { intptr P, Q; P = new int; *P = 1 Q = new int; *Q = 2; cout << *P << ‘ ’ << *Q << endl; *P = *Q + 3; cout << *P << ‘ ’ << *Q << endl; P = Q; cout << *P << ‘ ’ << *Q << endl; } ? P ? Q •••
Dynamic Allocation typedef int* intptr; void main () { intptr P, Q; P = new int; *P = 1 Q = new int; *Q = 2; cout << *P << ‘ ’ << *Q << endl; *P = *Q + 3; cout << *P << ‘ ’ << *Q << endl; P = Q; cout << *P << ‘ ’ << *Q << endl; } 1 P ? Q •••
Dynamic Allocation typedef int* intptr; void main () { intptr P, Q; P = new int; *P = 1 Q = new int; *Q = 2; cout << *P << ‘ ’ << *Q << endl; *P = *Q + 3; cout << *P << ‘ ’ << *Q << endl; P = Q; cout << *P << ‘ ’ << *Q << endl; } 1 P ? Q •••
Dynamic Allocation typedef int* intptr; void main () { intptr P, Q; P = new int; *P = 1 Q = new int; *Q = 2; cout << *P << ‘ ’ << *Q << endl; *P = *Q + 3; cout << *P << ‘ ’ << *Q << endl; P = Q; cout << *P << ‘ ’ << *Q << endl; } 1 P 2 Q •••
Dynamic Allocation typedef int* intptr; void main () { intptr P, Q; P = new int; *P = 1 Q = new int; *Q = 2; cout << *P << ‘ ’ << *Q << endl; *P = *Q + 3; cout << *P << ‘ ’ << *Q << endl; P = Q; cout << *P << ‘ ’ << *Q << endl; } 1 P 2 Q Output: 1 2 •••
Dynamic Allocation typedef int* intptr; void main () { intptr P, Q; P = new int; *P = 1 Q = new int; *Q = 2; cout << *P << ‘ ’ << *Q << endl; *P = *Q + 3; cout << *P << ‘ ’ << *Q << endl; P = Q; cout << *P << ‘ ’ << *Q << endl; } 5 P 2 Q •••
Dynamic Allocation typedef int* intptr; void main () { intptr P, Q; P = new int; *P = 1 Q = new int; *Q = 2; cout << *P << ‘ ’ << *Q << endl; *P = *Q + 3; cout << *P << ‘ ’ << *Q << endl; P = Q; cout << *P << ‘ ’ << *Q << endl; } 5 P 2 Q Output: 5 2 •••
Dynamic Allocation typedef int* intptr; void main () { intptr P, Q; P = new int; *P = 1 Q = new int; *Q = 2; cout << *P << ‘ ’ << *Q << endl; *P = *Q + 3; cout << *P << ‘ ’ << *Q << endl; P = Q; cout << *P << ‘ ’ << *Q << endl; } Memory leak! 5 P 2 Q •••
Dynamic Allocation typedef int* intptr; void main () { intptr P, Q; P = new int; *P = 1 Q = new int; *Q = 2; cout << *P << ‘ ’ << *Q << endl; *P = *Q + 3; cout << *P << ‘ ’ << *Q << endl; P = Q; cout << *P << ‘ ’ << *Q << endl; } Memory leak! 5 P 2 Q Output: 2 2 •••
Dynamic Allocation Memory leak! ••• *P = 7; cout << *P << ‘ ’ << *Q << endl; P = new int; delete P; P = NULL; Q = NULL; } 5 P 7 Q
Dynamic Allocation Memory leak! ••• *P = 7; cout << *P << ‘ ’ << *Q <<endl P = new int; delete P; P = NULL; Q = NULL; } 5 P 7 Q Output: 7 7
Dynamic Allocation Memory leak! ••• *P = 7; cout << *P << ‘ ’ << *Q << endl; P = new int; delete P; P = NULL; Q = NULL; } 5 P 7 Q ?
Dynamic Allocation Memory leak! ••• *P = 7; cout << *P << ‘ ’ << *Q << endl; P = new int; delete P; P = NULL; Q = NULL; } ? 5 P 7 Q
Dynamic Allocation Memory leak! ••• *P = 7; cout << *P << ‘ ’ << *Q << endl; P = new int; delete P; P = NULL; Q = NULL; } 5 P 7 Q
Dynamic Allocation Memory leaks! ••• *P = 7; cout << *P << ‘ ’ << *Q << endl; P = new int; delete P; P = NULL; Q = NULL; } 5 P 7 Q
NULL - Is a built-in constant that sets a pointer variable to something that can not be dereferenced - Also makes it clear that a pointer variable is in fact not pointing to anything - A garbage pointer may be non NULL and thus look like it’s pointing to something if (some_pointer = = NULL) cout << “pointer points to nothing” << endl; Dynamic Allocation
- Pointer variables can be initialized to NULL intptr a=NULL, b=NULL, c=NULL; - Probably a good habit to set pointer variables to NULL after deleting them Dynamic Allocation
Dynamic Allocation #include <iostream> using namespace std; typedef int* intptr; void main () { intptr ptr1; ptr1 = new int; *ptr1 = 12345; delete ptr1; cout << *ptr1 << endl; } Output?
Dynamic Allocation #include <iostream> using namespace std; typedef int* intptr; void main () { intptr ptr1; ptr1 = new int; *ptr1 = 12345; delete ptr1; ptr1 = NULL; cout << *ptr1 << endl; } Output?
- Using NULL does not guarantee that that you protect yourself from doing something silly as in: Dynamic Allocation
Dynamic Allocation #include <iostream> using namespace std; typedef int* intptr; void main () { intptr ptr1; ptr1 = new int; *ptr1 = 12345; delete ptr1; ptr1 = NULL; ptr1 = new int; cout << *ptr1 << endl; } Output?
Dynamic Allocation #include <iostream> using namespace std; typedef int* intptr; void main () { intptr ptr1, ptr2; ptr1 = new int; *ptr1 = 12345; delete ptr1; ptr1 = NULL; ptr2 = new int; ptr1 = new int; cout << *ptr1 << endl; } Output?
Dynamic Allocation - When dealing with pointers, you are responsible for ensuring they do not dangle Note: - Dynamic allocation is one of the most important topic of this course. So you need understand it very well.
Link List: Linked structures - Linked lists often provide an elegant alternative to structures such as arrays - A linked list is readily created in most procedural languages Linked lists are often represented in the following manner:
Linked Lists Pointer to next node top Data 27 -38 4 36 Last node’s pointer is NULL node
Linked List - The simplest linked structure - Sometimes called a linear linked list - The result of having an initial pointer to a node - And dynamically created nodes that point to other nodes - A dynamic incarnation of a simple array - Both have their advantages
Linked Lists - Big advantage over array in that linked list is dynamically created - Use only as many nodes as required for data - List grows and shrinks accordingly - Linked lists are made up of a pointer (“top” in this case) that points to the first of a collection of homogeneous nodes - Unlike the nodes, top contains no data top is not dynamically created while the rest of the linked structure is
Declaration for linked list class node; typedef node* nodeptr; class node { public: int number; nodeptr next; }; //-------------------------------- int main ( ) { nodeptr top; …. } Only variable declared
Linked Lists - All that exists at this time is an uninitialized pointer to a node - No nodes have been allocated yet - To make it clear the linked list is empty top = NULL; ••• NULL is a special C++ constant •••
Dereferencing: Allocating a node - The Code: top = new node; - Allocates space for a new node and place its starting memory address in top
Dereferencing - Given that a node exists and given that a pointer exists that contains the node’s address, the contents of the node may be modified - Again, using a pointer to reference storage is called dereferencing top -> number = 123; top -> next = NULL; Note the arrow notation that allows access to a field within a node
- Now have: 123 Dereferencing Remember that top is a declared variable -- a pointer to a node top This node is not a variable -- it is dynamically allocated via the new statement
top = new node; // again! New (again) top now points to a new node top top 123 123 Old node still exists, but can no longer be accessed -- memory leak!
Delete - Linked lists are dynamic which means they can grow and shrink appropriately - Grow with new - Shrink with delete