Sie sind auf Seite 1von 22

Data Structures & Algorithms

Lecture 2: Pointers & Dynamic Memory Allocation

Dr. Muhammad Shahzad


mshehzaad@hotmail.com

Department Of Computing (DOC),


School of Electrical Engineering & Computer Science (SEECS),
National University of Sciences & Technology (NUST)

04/10/2016
Recap slide

Data Structure is a systematic way to organize data in order


to use it efficiently

An algorithm is an effective method for solving a problem


using a finite sequence of instructions

Data types:
Primitive Data Types
- Bool, Int, float etc.
User-Defined Data Types (UDTs)
- Aggregate data types e.g., structures, array-of-integers etc.
Abstract Data Types (ADTs)
- Does not specify how the data type is implemented
- In an object-oriented language such as C++, an ADT and its
implementation together make up a class
M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 2
Todays lecture

Referencing vs pointers
Arrays & dynamic memory allocation
Stack vs heap
The new operator & memory leaks
Concept of shalow/deep copying
Void pointer

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 3
Differences between references & pointers

Consider the following declarations:


int n=5, *p = &n, &r = n;

A reference variable must be initialized in its declaration as a


reference to a particular variable, and this reference cannot be
changed, meaning that a reference variable CANNOT be null

A reference variable r can be considered a different name for a


variable n
If n changes then r changes as well. This is because a reference
variable is implemented as a constant pointer to the variable

cout << n << ' ' << *p << ' ' << r << endl;
*p = 9;?
Output: 5 5 5 r = 10;?
M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 4
Differences between references & pointers

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 5
Constant pointer vs pointer constant

The declaration int& r = n; actually can be replaced by


int *const r = &n;
where r is a constant pointer to an integer, which means that
the assignment r = q; where q is another pointer, is an error
because the value of r cannot change
However, the assignment *r = 1; is acceptable if n is NOT a
constant integer
It is important to note the difference between the
type int *const and the type const int *
where const int * is a type of pointer to a constant integer:
const int *s = &m;
after which the assignment s = &m; where m in an integer
(whether constant or not) is admissible, but the assignment
*s = 2; is erroneous, even if m is not a constant
M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 6
Array names as pointers

#include <iostream>

void main() {
const SIZE = 5

int i, arr[SIZE] = {98, 87, 92, 79, 85};

for(i=0; i<SIZE; i++)


cout << arr[i] << *(arr + i) << endl;
}

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 7
Dynamic memory allocation

Arrays are useful, however we must know in advance about


the amount of memory required

In many situations, we do not know exact size required until


runtime

Reserving maximum wastes memory

Here comes the concept of dynamic memory allocation

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 8
Stack vs Heap

When a program is loaded into memory, it is organized into


three areas of memory, called segments:
text segment (code segment / instruction)
stack segment
heap segment

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 9
Stack vs Heap

Stack:
Special region of computer's memory that stores temporary
variables created by each function, including the main()
Stack variables only exist in the block of code in which they
were declared (unless declared static)

Advantages:
Memory managed automatically
CPU organizes stack memory therefore reading from and
writing to stack variables is very fast and efficient
Disdvantages:
Size limits (depending on the OS)
Large chunks of memory, such as very large arrays, should
not be allocated on the stack to avoid overfilling the stack
memory (known as stack overflow)
M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 10
Stack vs Heap

Heap:
Region of your computer's memory that is NOT managed
automatically

Advantages:
More free-floating region of memory i.e., only limited by the
size of virtual memory (i.e., RAM and swap space)
May be accessed outside of the block in which it was
allocated
Disadvantage:
Needs to be explicitly freed by the program Memory leaks

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 11
Heap vs Stack
Stack Heap
local variables are put on the stack global variables are on the heap
-unless they are also declared as
static local variables are on the heap
'static
(this is how they keep their value
function parameters are allocated between function calls)
on the stack
memory allocated by new, malloc
local variables that are declared on and calloc are on the heap
the stack are not automatically
The heap segment provides more
initialized by the system so they
stable storage of data for a program;
usually have garbage in them until
you set them memory allocated in the heap
remains in existence for the duration
variables on the stack disappear
of a program.
when the function exits (thus, if a
function is called multiple times, it's The memory allocated in the heap
local variables and parameters are area, if initialized to zero at program
recreated and destroyed each time start, remains zero until the program
the function is called and exited). makes use of it. Thus, the heap area
need not contain garbage.

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 12
Dynamic memory allocation

To avoid wasting memory, array allocation or deallocation


can take place at run time

To allocate memory, we need to use the new operator


Reserves the number of bytes requested by the declaration
Returns the address of the first reserved location or NULL if
sufficient memory is not available

To deallocate memory (which has previously been allocated


using the new operator) we need to use the delete operator
Releases a block of bytes previously reserved. The address of
the first reserved location is passed as an argument to delete.

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 13
The new operator

C++ provides a different approach to obtain dynamic


memory
new keyword obtains memory from OS and returns a
pointer to starting location

int x = 10;
int *ptr;

ptr = new int;


*ptr = x;
cout<<*ptr;

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 14
Memory leaks delete operator

If your program reserves many chunks of memory using new,


eventually all the available memory will be reserved and system
will crash
To ensure safe and efficient use of memory, new is matched by a
corresponding delete
If the program terminates the memory is released automatically,
however, if a function allocates memory using new and doesn't
release it then the pointer is destroyed but not the memory which
causes waste of memory
E.g., consider two lines of code Correct should be
p = new int;
p = new int;
p = new int;
delete p;
where after allocating one cell for an integer, p = new int;
the same pointer p is used to allocate another cell

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 15
Case of 1D array

cout << "Enter array size: ";


cin >> SIZE;

int *arr;
arr = new int[SIZE]; // allocation

delete [] arr; // deallocation

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 16
Case of 2D arrays

cout << "Enter numRows and numCols: ";


cin >> numRows >> numCols;

int **arr2D;
arr2D = new int* [numRows]; // allocation

for(i=0; i<numRows; i++)


arr2D[i] = new int[numCols];

for(i=0; i<numRows; i++) // deallocation


delete [] arr2D[i];

delete [] arr2D;
(individual elements can be accessed using
indices!! (e.g., arr2D[0][2]=10;))

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 17
Shallow / Deep Copy

struct Node{
char *name; Output:
int age; => Wendy 20 Wendy 30
Node(char *n = , int a=0) {
name = strdup(n); The reason for this is that the
age = a; definition of Node does not
} provide a copy constructor
};
Node(const Node&);
Node node1(Roger, 20);
Node node2(node1); // node2 = node1;
The intention of these declarations is to create object node1, assign values to
the two data members in node1, and then create object node2 and initialize
its data members to the same values as in node1
strcpy(node2.name, Wendy);
node2.age = 30;
cout<<node2.name<< <<node2.age<< <<node1.name<< <<node1.age;
M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation
Shallow / Deep Copy

If a user copy constructor is missing, the constructor is


generated automatically by the compiler
But the compiler-generated copy constructor performs
member-by-member copying; and
since name is a pointer, the copy constructor copies the string
address node1.name to node2.name, but NOT the string
content, so that right after execution of the declaration

Node node1(Roger, 20); strcpy(node2.name, Wendy);


Node node2(node1); // or node2 = node1; node2.age = 30;

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 19
Shallow / Deep Copy
Node node1(Roger, 20);
struct Node{ Node node2(node1); // or node2 = node1;
char *name;
int age;
Node(char * n=, int a=0) {
name = strdup(n);
strcpy(name, n);
age = a;
}
Node(const Node& n){ strcpy(node2.name, Wendy);
name = strdup(n.name); node2.age = 30;
age = n.age;
}
};

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation
Void pointer

A void* is a generic pointer meaning that pointer of any type


can be assigned to the void pointer

Once assigned the type of void* is the same as that of


assigned pointer type

Dereferencing a void* is a syntax error


void* sPtr;
int num;
int z[3] = {1,2,3};
sPtr = z;
num = *sPtr; // ERROR
num = *(int*) sPtr; // correct version

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 21
Next lecture topic:

Linked lists

M. Shahzad: Data Structures & Algorithms Lecture 2: Pointers and dynamic memory allocation 22