Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 27

Dynamically Allocated Memory

pointer variables and the heap

Pointer Variables
a pointer is a variable which holds the address of something else

called indirect addressing pointer

what is pointed to a value of some type

Do not mistake the pointing finger for the moon

a Zen saying

Some Uses of Pointer Variables


reference parameters in C++ and class instances in Java
the pointer is "hidden"

dynamically (run-time) allocated arrays linked data structures


linked lists

"lifetime" of a variable
is a run-time concept period of time during which a variable has memory space associated with it
begins when space is allocated ends when space is de-allocated

three categories of "lifetime"


static - start to end of program execution automatic (stack) - start to end of declaring function's execution heap - starts with "new"; ends when:
Java: run-time system collects "garbage" C++: "delete" statement executed

data memory model


static data automatic data space for global variables run-time stack - activation records added and removed as program runs (expands and shrinks in an orderly LIFO manner) space for variables allocated at run-time using "new" (allocation and de-allocation requests occur in unpredictable order)

heap data

Heap Variables
are accessed indirectly via a pointer variable memory space is explicitly allocated at run-time (using new) space is allocated from an area of run-time memory known as the heap in C++ space must be explicitly returned (using delete) to avoid memory leak
C++ programmers are responsible for memory management

Declaring Pointer Variables


syntax
<data type> * <pointer name>; C++ pointers are typed

some examples
int * intPointer;

Time * timePointer;
intPointer ? timePointer ?

intPointer and timePointer are automatic variables

Assigning a value to a pointer variable


the value of a pointer variable is a memory address assign address of an existing variable
int number; intPointer = &number;

use "new" to allocate space in the heap


intPointer = new int; address of heap memory space allocated becomes the value of the pointer variable heap memory
intPointer

Dereferencing
heap variables do not have a name of their own
are anonymous variables

*intPointer refers to the value pointed to by intPointer


intPointer is the finger; *intPointer is the moon

what happens?
intPointer = 36; *intPointer = 36; (*intPointer)++; cout << *intPointer; intPointer = null; intPointer

*intPointer

Returning Heap Space


done by using the delete statement syntax

delete <pointer variable>;

example
float * fPointer = new float; cin >> (*fPointer); -----delete fPointer;

Pointers - Summary
a pointer variable holds a memory address and can be used to create and access dynamic variables dynamic (heap) variables are explicitly created at run-time (using new) memory for dynamic variables is allocated in an area of memory called the heap space used for dynamic variables needs to be freed (using delete) to avoid memory leaks

using pointers to dynamically allocate arrays

a C++ automatic array


int entry [31];
entry
34
0

value has to be known at compile time

45
1

15
2

--------------------

36
30

entry[0] = = *entry

NO HEAP MEMORY SPACE IN USE!

C++ dynamic arrays


can use dynamic memory allocation to postpone decision about array capacity until run-time
array space will be on the heap pointer to array's beginning is not on the heap

float * dynArray; // declare pointer only dynArray = new float [max]; // max is a variable // use of dynamic array the same as use of an automatic array delete [ ] dynArray; // free heap space

Stack class using a dynamic array


changes needed ?
data structure has changed so private data members will be different constructor has to allocate the dynamic array
needs parameter to indicate capacity once allocated capacity does not change

operations are the same


data member rather than constant for capacity

use of the heap requires added methods


destructor, copy constructor, operator=

Stack class
data members needed?
SE * myArray; int myTop; int myCapacity;
someStack

Constructor
must allocate the dynamic array needs a parameter to know how big an array to allocate
Stack::Stack (int size) { myCapacity = size; myArray = new SE[myCapacity]; assert (myArray != null); myTop = -1; }

myArray
myTop myCapacity

a Stack object
void func ( ) { Stack someStack (5); ----------}
someStack

myArray
myTop

-1

myCapacity 5

when func returns space for its activation record on the run-time stack is reclaimed

This space in on the stack

This space in on the heap

destructor
needed in order to prevent "memory leaks"
heap memory space which is no longer accessible but has not been returned (using delete)

destructor is a method that is called implicitly when the function in which an object was declared returns
compiler provides a "default destructor" nothing more is needed unless the object makes use of heap memory space (allocates space using new)

to provide a destructor for Stack


in declaration: in implementation: { } ~Stack( ); // class destructor Stack::~Stack( ) delete [ ] myArray;

copy constructor
needed in order to make a deep rather than a shallow copy of an object when is a copy of an object made?
a value parameter requires a copy of the argument
void someFunc (Stack s) { ---- }

one object is created as a copy of an existing object


Stack a (10); Stack b = a; // or Stack b (a);

a function/method returns an object


Stack func ( ) { Stack stackToBeReturned (8); ----return stackToBeReturned; }

a shallow copy
compiler provides a default copy constructor
it makes a shallow copy when a copy is needed nothing more is needed unless the object makes use of heap memory space (allocates space using new) Stack a (8); Stack b (a); a
myArray myTop

b
myArray myTop

myCapacity 8

myCapacity 8

a deep copy
the copy must have its own heap memory space, the contents of which is the same as the object it is a copy of
Stack a (8); Stack b (a); a
myArray myTop

b
myArray myTop

myCapacity 8

myCapacity 8

a copy constructor
myClass (const myClass & sourceObj); myClass::myClass (const myClass & sourceObj) { //copy all non-heap data members using = //allocate heap space required by the copy //copy data stored in sourceObj's heap //memory to new object's heap memory }
makes a new deep copy of an existing object

copy constructor for Stack class


declaration

Stack (const Stack & sourceStack); Stack::Stack (const Stack & sourceStack) { myCapacity = sourceStack.myCapacity; myTop = sourceStack.myTop; myArray = new SE [myCapacity]; assert (myArray != null); for (int pos = 0; pos < myTop; pos++) { myArray[pos] = sourceStack.myArray[pos]; } }

implementation

= replaces an object with a copy of an existing object


stackA = stackB; compiler provided operator= replaces stackA with a shallow copy of stackB heap space used by the "old" stack A becomes garbage a class using heap memory must provide its own operator=
return heap memory currently used by stackA replace stackA with a deep copy of stackB

operator=
void operator= (const myClass & SourceObj); void myClass::operator= (const myClass & SourceObj); { //deallocate heap space used by left hand operand //copy all non-heap data members using = //allocate new heap space for the left hand operand //copy data stored in sourceObj's heap memory //to left hand operand's heap memory } same job that is done by the copy constructor

operator= for Stack class


declaration

void operator= (const Stack & sourceStack); void Stack::operator= (const Stack & sourceStack) { if (this != &sourceStack) // check for self copy { delete [ ] myArray; // deallocate previous array // same code as in the copy constructor // to make a deep copy of sourceStack } }

implementation

You might also like