Presentation is loading. Please wait.

Presentation is loading. Please wait.

Pointer: Dynamic Allocation

Similar presentations


Presentation on theme: "Pointer: Dynamic Allocation"— Presentation transcript:

1 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

2 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 FFFF represents 64K of memory - 64 * 1024 = 65,536 memory locations 0000 0001 0002 0003 0004 0005 •• FFFF

3 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

4 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

5 Dynamic Allocation - It is possible to explicitly declare a variable
that contains the address of other variables - Creating variables that are pointers

6 Dynamic Allocation typedef
int* intptr; int main ( ) { intptr ptr1; Must be a pointer to a valid C++ type (either built-in or user defined type) intptr is a pointer to an integer •••

7 Dynamic Allocation Syntax notes: is the same as ... int main ( ) {
int* ptr1; int* ptr2; int* ptr3; int main ( ) { int *ptr1, *ptr2, *ptr3; ••• •••

8 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

9 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 •••

10 Dynamic Allocation - Unlike “normal” variables, pointers must be explicitly dereferenced *ptr1 = 200; Store 200 in the 4 bytes pointed to by ptr1

11 Assign 200 to integer variable i
Dynamic Allocation - Other manipulation may take place i = *ptr1; Assign 200 to integer variable i

12 Dynamic Allocation Other manipulation may not sensibly take place
i = ptr1; Assign the address that ptr1 points to to integer variable i?

13 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

14 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

15 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; P = Q; } ? P ? Q •••

16 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; P = Q; } ? P ? Q •••

17 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; P = Q; } 1 P ? Q •••

18 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; P = Q; } 1 P ? Q •••

19 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; P = Q; } 1 P 2 Q •••

20 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; P = Q; } 1 P 2 Q Output: 1 2 •••

21 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; P = Q; } 5 P 2 Q •••

22 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; P = Q; } 5 P 2 Q Output: 5 2 •••

23 Dynamic Allocation typedef int* intptr; void main () { Memory leak!
intptr P, Q; P = new int; *P = 1 Q = new int; *Q = 2; cout << *P << ‘ ’ << *Q << endl; *P = *Q + 3; P = Q; } Memory leak! 5 P 2 Q •••

24 Dynamic Allocation typedef int* intptr; Memory leak! void main () {
intptr P, Q; P = new int; *P = 1 Q = new int; *Q = 2; cout << *P << ‘ ’ << *Q << endl; *P = *Q + 3; P = Q; } Memory leak! 5 P 2 Q Output: 2 2 •••

25 Dynamic Allocation Memory leak! ••• *P = 7;
cout << *P << ‘ ’ << *Q << endl; P = new int; delete P; P = NULL; Q = NULL; } 5 P 7 Q

26 Dynamic Allocation Memory leak! ••• *P = 7; 5
cout << *P << ‘ ’ << *Q <<endl P = new int; delete P; P = NULL; Q = NULL; } 5 P 7 Q Output: 7 7

27 Dynamic Allocation Memory leak! ••• *P = 7;
cout << *P << ‘ ’ << *Q << endl; P = new int; delete P; P = NULL; Q = NULL; } 5 P 7 Q ?

28 Dynamic Allocation Memory leak! ••• *P = 7;
cout << *P << ‘ ’ << *Q << endl; P = new int; delete P; P = NULL; Q = NULL; } ? 5 P 7 Q

29 Dynamic Allocation Memory leak! ••• *P = 7;
cout << *P << ‘ ’ << *Q << endl; P = new int; delete P; P = NULL; Q = NULL; } 5 P 7 Q

30 Dynamic Allocation Memory leaks! ••• *P = 7;
cout << *P << ‘ ’ << *Q << endl; P = new int; delete P; P = NULL; Q = NULL; } 5 P 7 Q

31 Dynamic Allocation 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;

32 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

33 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?

34 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?

35 Dynamic Allocation - Using NULL does not guarantee that that you protect yourself from doing something silly as in:

36 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?

37 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; cout << *ptr1 << endl; } Output?

38 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.

39 Link Lists

40 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:

41 Linked Lists Pointer to next node top Data 27 -38 4 36
Last node’s pointer is NULL node

42 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

43 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

44 Only variable declared
Declaration for linked list class node; typedef node* nodeptr; class node { public: int number; nodeptr next; }; // int main ( ) { nodeptr top; …. } Only variable declared

45 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 •••

46 Dereferencing: Allocating a node
- The Code: top = new node; - Allocates space for a new node and place its starting memory address in top

47 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

48 Dereferencing top - Now have: Remember that top is a
declared variable -- a pointer to a node top 123 This node is not a variable -- it is dynamically allocated via the new statement

49 New (again) top top top = new node; // again! top now points
to a new node top top 123 123 Old node still exists, but can no longer be accessed -- memory leak!

50 Delete - Linked lists are dynamic which means they can
grow and shrink appropriately - Grow with new - Shrink with delete

51 Delete top top - delete top; top now contains garbage ? 123 123
Node might still exist, but is at the control of the OS

52 Insert - Inserting many nodes:
- Important to be able to insert more than a single node into a linked list

53 Insert - Assume an existing linked list structure and definition nodeptr newnode; top 27 -38 4 36

54 Insert newnode = new node; newnode -> number = 123;
newnode -> next = top; top = newnode; newnode This code assumes you always want to place a newly allocated node at the front of the list top 123 27 -38 4 36

55 Searching - Many operations upon a linked structures involve searching. bool search (nodeptr top, int key) { nodeptr curr=top; bool found=false; while ((curr != NULL) && (!found)) if (curr -> number == key) found = true; else curr = curr -> next; return (found); }

56 More on Inserting - Have seen inserting a node to the front of a linked list - Possible that this might not be satisfactory - If a list is to be maintained in sorted order (for example), an insert might have to be done in the middle or the the end of the list

57 Find insertion point (prev) Insert More on Insert
void insert (nodeptr& top, int item) { nodeptr curr=top, prev=NULL, newnode; bool found=false; newnode = new node; newnode -> number = item; while ((curr != NULL) and (!found)) if (item > curr -> number) prev = curr; curr = curr -> next; } else found = true; newnode -> next = curr; if (prev == NULL) top = newnode; prev -> next = newnode; Find insertion point (prev) Insert

58 Deleting - Removing items from a linked list will normally require a
search and knowledge of different cases of delete (much like insert) - Deleting the first node of a linked list requires the manipulation of the “top” pointer - Deleting a node in the middle of a linked list requires the manipulation of pointers within allocated nodes -- “top” pointer will remain unchanged - Deleting at the end of a linked list requires the same operations as delete in the middle

59 Deleting Double dereference void remove (nodeptr& top, int key) {
nodeptr curr, temp; // Code assumes key will be found if (key == top -> number) temp = top; top = top -> next; } else curr = top; while (curr -> next -> number != key) curr = curr -> next; temp = curr -> next; curr -> next = curr -> next -> next; delete temp; Double dereference

60 Deleting - For every node that is allocated via new, there should be a
node given back to the OS via delete - This implies that a function should probably exist to destroy an existing linked list void destroy (nodeptr& top) { nodeptr curr=top, temp; while (curr != NULL) temp = curr; curr = curr -> next; delete temp; } top = NULL; If you declare and create a linked list within a function without destroying it, you will have a memory leak when you leave the function ends

61 Copying - Functions can work with more than one linked list at a time
- Here is a function that copies one linked list to another: void copy (nodeptr atop, nodeptr& btop) { nodeptr acurr, bcurr; destroy (btop); // deleted previous nodes in the list if there is any if (atop != NULL) { btop = new node; btop -> number = atop -> number; acurr = atop; bcurr = btop; while (acurr -> next != NULL) { bcurr -> next = new node; acurr = acurr -> next; bcurr = bcurr -> next; bcurr -> number = acurr -> number; } bcurr -> next = NULL;

62 Linked lists - Linked lists are general purpose structures that can be
manipulated to solve a diverse set of problems - Working successfully with linked lists takes study and practice - It really helps if you understand the basics < See: Example 1>

63 Object-Oriented Programming
with Link List This lecture prepared by the instructors at the University of Manitoba in Canada and has been modified by Dr. Ahmad Reza Hadaegh

64 … but in addition, now have another class:
Linked Lists and Classes class node; typedef Node* NodePtr; class node { public: int number; NodePtr next; }; As before … but in addition, now have another class:

65 - A linked list is now defined as a class itself
Linked Lists and Classes class LL { private: NodePtr top; void destroy(NodePtr&); public: LL(); ~LL(); void buildLL(int); void printLL(); }; - A linked list is now defined as a class itself

66 Linked Lists and Classes void main () { LL list1, list2, list3; … }
list1, list2, and list3 are three instances of the LL class. list1, list2, and list3 are also called objects.

67 Linked Lists and Classes
- A class is made up of data and methods class LL { private: NodePtr top; void destroy(NodePtr&); public: LL(); ~LL(); void buildLL(int); void printLL(); }; datum This class definition has 5 method prototypes and one datum. method

68 Linked Lists and Classes
- Data and methods of a class definition can be public or private - Public: - Accessible by the world (scoping rules still apply) - Private: - Accessible only by member functions

69 Linked Lists and Classes
- Placing data and methods within the private portion of a class definition protects them from “outside” harm - Sometimes called data hiding - The only way hidden data and methods can be accessed is indirectly via public methods - Methods and data are bound together - Encapsulation

70 Linked Lists and Classes
class LL { private: NodePtr top; void destroy(NodePtr&); public: LL(); ~LL(); void buildLL(int); void printLL(); }; Can only be accessed by A linked list (LL) is now an encapsulated package of data and a limited number of methods that work upon that data.

71 Linked Lists and Classes
- In the procedural linked list example - Top pointers were set to NULL before use - Nodes within linked list were deleted before linked list left scope - Remember that the top pointer has been defined as automatic and will cease to exist when the linked list leaves scope - The allocated memory will live on until deleted - Programmer’s responsibility to ensure initialization and destruction takes place properly

72 Linked Lists and Classes
- Objects can have constructors - Method that is automatically invoked when an object is created - Allows for initialization to take place - Objects can have destructors - Method that is automatically invoked when an object leaves scope - Allows for clean up to take place - Constructors and destructors are not normally called explicitly

73 Linked Lists and Classes
class LL { private: NodePtr top; void destroy(NodePtr&); public: LL(); ~LL(); void buildLL(int); void printLL(); }; constructor destructor

74 Linked Lists and Classes
Scope resolution operator -- lets the compiler know that what you’re defining is a member function of the class LL LL::LL() { // Linked list constructor top = NULL; }

75 Linked Lists and Classes
LL::~LL() { // Linked list destructor -- will call a private // member function “destroy” that will perform // a deep deletion of the linked list object destroy (top) ; } This destructor will automatically be invoked when an instance of LL leaves scope

76 Linked Lists and Classes
void LL::destroy(NodePtr& head) { // Deep delete a linked list pointed at by “head” NodePtr curr, temp; curr = head; while (curr != NULL) temp = curr; curr = curr->next; delete temp; } head = NULL; Very much like a regular procedural function -- does not operate directly on data components of the object

77 Linked Lists and Classes
void LL::buildLL(int size) { // "build” will create an ordered linked list consisting // of the first "size" even integers NodePtr newNode; int i; destroy(top); //Destroy self before building linked list. for (i=size;i>0;i--) { newNode = new (Node); newNode->next = top; newNode->number = i*2; top = newNode; }

78 Linked Lists and Classes
void LL::printLL() { // "print" will output the entire linked list to // the standard output device -- // one "number" per line. NodePtr curr; curr = top; while (curr != NULL) cout << curr->number << endl; curr = curr->next; }

79 Linked Lists and Classes
Member functions are invoked as follows: void main () { LL list1, list2, list3; list1.buildLL(10); list2.buildLL(20); list3.buildLL(50); list1.buildLL(40); list1.printLL(); list2.printLL(); list3.printLL(); }

80 Linked Lists and Classes
Member functions are called as if they were a part of a structure -- which they are void main () { LL list1, list2, list3; list1.buildLL(10); list2.buildLL(20); list3.buildLL(50); list1.buildLL(40); list1.printLL(); list2.printLL(); list3.printLL(); }

81 Linked Lists and Classes
Constructor called 3 times here void main () { LL list1, list2, list3; list1.buildLL(10); list2.buildLL(20); list3.buildLL(50) list1.buildLL(40); list1.printLL(); list2.printLL(); list3.printLL(); } private member function “destroy” called 4 times indirectly here Destructor called 3 times here

82 Shallow vs. Deep Copy Assume the following: Constructor called -- top
pointer set to NULL void main () { LL list1, list2; list1.buildLL(4); list2 = list1; } Build a linked list of size 4 Shallow copy of list1 made to list2 Destructor called for both list1 and list2

83 Shallow vs. Deep Copy void main () { LL list1; list1.buildLL(4);
} A shallow copy in this circumstance simply means that the data members of list1 are copied to the data members of list2 -- the top pointer of list1 and list2 will now point to the same place

84 Shallow vs. Deep Copy void main () { LL list1; list1.buildLL(4);
} Creating an alias is useful, but not likely the result you were looking for here -- really want a “copy” of the entire linked list list1.top 2 4 6 8 list2.top

85 Shallow vs. Deep Copy void main () { LL list1, list2;
list1.buildLL(4); list2 = list1; } Creating an alias is useful, but not likely the result you were looking for here -- really want a “copy” of the entire linked list list1.top list2.top 2 4 6 8 2 4 6 8

86 Shallow vs. Deep Copy - A deep copy implies that the actual structure is copied -- not the data members - It is possible to write a member function that does an explicit deep copy of one linked list to another, but there are times when a deep copy would best be done implicitly - Initialization (as in the previous example) - Passing a linked list to a function as a value parameter - Would then be able to “protect” a linked list much as you can protect an integer - Be cognisant of the overhead involved

87 Shallow vs. Deep Copy - Returning a linked list from a function
- What problem would you currently have if you tried to return a linked list from a function?

88 Copy Constructor - Implicit deep copying can be performed by creating a copy constructor - Copy constructor is a function that will automatically be called when a deep copy is likely required - As in the previous three cases So...

89 Copy Constructor class LL { private: NodePtr top;
void copy(NodePtr, NodePtr&); // Deep copy of 1st to 2nd void destroy(NodePtr&); public: LL(); ~LL(); LL(const LL&); // Copy constructor void buildLL(int); void printLL(); };

90 void LL::copy(NodePtr atop, NodePtr& btop)
{ // Performs a deep copy from linked list pointed to // by “atop” to linked list pointed to be “btop”. NodePtr acurr, bcurr; destroy (btop); // Free any storage used by target linked list if (atop != NULL) btop = new (node); btop->number = atop->number; acurr = atop; bcurr = btop; while (acurr->next != NULL) bcurr->next = new (node); acurr = acurr->next; bcurr = bcurr->next; bcurr->number = acurr->number; } bcurr->next = NULL;

91 Copy Constructor LL::LL(const LL& source) { copy (source.top, top); }
// Copy constructor -- does a deep copy of linked list. copy (source.top, top); } <See: Example 1>


Download ppt "Pointer: Dynamic Allocation"

Similar presentations


Ads by Google