Dynamic Memory Allocation in C++
An Introduction
Prof. David Bernstein
James Madison University
Computer Science Department
Motivation An Observation:
o We often don't know how much space we will need to store things at "compile time"
o Dynamic memory allocation is the allocation of memory at "run time"
Past Experience:
o You've seen some of this before in Java, since all objects use memory that is allocated at "run time"
Diferences between Static and Dynamic Memory Allocation Dynamically allocated memory is kept on the memory heap (also known as
the free store)
Dynamically allocated memory can't have a "name" it must be referred to
Declarations are used to statically allocate memory, the new operator is used to
dynamically allocate memory
Pointing to Memory Allocated at Run Time An Example:
o
o int *ptr;
o
Illustration:
o
Pointing to Memory Allocated at Run Time (cont.) An Example:
o
o ptr = new int;
o
Illustration:
o
Using Memory Allocated at Run Time An Example:
o
o *ptr = 7;
o
Illustration:
o
Run Time Allocation of Arrays An Example:
o
o int *a;
o
Illustration:
o
Run Time Allocation of Arrays (cont.) An Example:
o
o a = new int[3];
o
Illustration:
o
Run Time Allocation of Arrays (cont.)
An Example:
o
o *a = 300;
o *(a+1) = 301;
o *(a+2) = 302;
o
Illustration:
o
Run Time Allocation of Arrays (cont.) An Observation:
o *a and a[0] are syntactically different ways to refer to the same value
An Explanation:
o The [] operator performs pointer arithemtic and de-references the resulting pointer.
Returning Memory to the Heap How Big is the Heap?
o It can only contain as much physical memory as you have installed or as much virtual memory as your operating system can make available (if it supports virtual memory)
Running Out of Memory:
o Most applications request memory from the heap when they are running
o It is possible to run out of memory (you may even have gotten a message like "Running Low On Virtual Memory")
o So, it is important to return memory to the heap when you no longer need it
Returning Memory to the Heap (cont.) The Opposite of new:
o In C++: The delete operator in C++
o In Java: The JVM has a garbage collector that returns unused memory
An Example:
o
o delete ptr;
o
Illustration:
o
Returning Memory to the Heap (cont.) Dangling Pointers:
o The delete operator does not delete the pointer, it takes the memory being pointed to
and returns it to the heap
o It does not even change the contents of the pointer
o Since the memory being pointed to is no longer available (and may even be given to another application), such a pointer is said to be dangling
An Example:
o
o ptr = NULL;
o
Illustration:
o
Returning Memory to the Heap (cont.) Remember:
o Return memory to the heap before undangling the pointer
What's Wrong with the Following:
o
o ptr = NULL;
o
o delete ptr;
o
Returning Memory to the Heap (cont.) What About Arrays?
o You want to return all of the memory to the heap
o So, a different form of the delete operator is needed
o Also, the memory allocator must keep track of the size of the array
An Example:
o
o delete[] a;
o
Illustration:
o
Returning Memory to the Heap (cont.) An Example:
o
o a = NULL;
o
Illustration:
o
Memory Leaks An Explanation:
o Memory leaks when it is allocated from the heap using the new operator but not
returned to the heap using the delete operator
An Example:
o
o int *otherptr;
o
Illustration:
o
Memory Leaks (cont.) An Example:
o
o otherptr = new int;
o
Illustration:
o
Memory Leaks (cont.) An Example:
o
o *otherptr = 4;
o
Illustration:
o
Memory Leaks (cont.)
An Example:
o
o otherptr = new int;
o
Illustration:
o
Memory Leaks (cont.) An Example:
o
o *otherptr = 5;
o
Illustration:
o
Dynamic Allocation of Objects A Simple Class to Get Us Started
cppexamples\memory\Weight.h
#ifndef WEIGHT
#define WEIGHT
/**
* A very simple weight class (used to demonstrate memory
* allocation for objects)
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
class Weight
{
public:
int pounds, ounces;
Weight(int lbs, int oz);
};
#endif
cppexamples\memory\Weight.cpp
#include "Weight.h"
/**
* A very simple weight class (used to demonstrate memory
* allocation for objects)
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
/**
* Explicit Value Constructor
*
* @param lbs The number of pounds in this Weight
* @param oz The number of ounces in this Weight
*/
Weight::Weight(int lbs, int oz)
{
pounds = lbs;
ounces = oz;
}
Dynamic Allocation of Objects (cont.) An Observation:
o We can dynamically allocate memory for objects
An Example:
o
o Weight *w;
o
Illustration:
o
Dynamic Allocation of Objects (cont.) An Example:
o
o w = new Weight(6,11);
o
Illustration:
o
Dynamic Allocation of Objects (cont.) De-referencing Pointers to Objects:
o Works the same as with other pointers
An Example:
o
o (*w).pounds
o
A "Shorthand" Operator:
o
o w->pounds
o
o Inside of a class you can use this->
Dynamic Allocation of Objects (cont.) A More Complicated Class
cppexamples\memory\Person.h
/**
* A person
*
* Author: CS240
* Department of Computer Science
* James Madison University
*
*/
#define PERSON
#include < string.h >
class Person {
public:
char *personalName, *familyName;
int age;
/**
* Constructor
*
* Purpose: Construct a new Person
*
* Arguments: pn - A pointer to the personal name
* fn - A pointer to the family name
* n - The person's age
*
* Side Effect: None
*
* Returns:
*/
Person(char *pn, char*fn, int n);
/**
* Destructor
*
* Purpose: Destroy a new Person
*
* Arguments: None
*
* Side Effect: None
*
* Returns:
*/
~Person(void);
};
cppexamples\memory\Person.cpp
/**
* Implementation of the Person class
*
* Author: CS240
* Department of Computer Science
* James Madison University
*
*/
#ifndef PERSON
#include "Person.h"
#endif
/**
* Constructor
*
* Purpose: Construct a new Person
*
* Arguments: pn - A pointer to the personal name
* fn - A pointer to the family name
* n - The person's age
*
* Side Effect: None
*
* Returns:
*/
Person::Person(char *pn, char*fn, int n) {
personalName = new char[strlen(pn)+1];
familyName = new char[strlen(fn)+1];
strcpy(personalName, pn);
strcpy(familyName, fn);
age = n;
}
/**
* Destructor
*
* Purpose: Destroy a new Person
*
* Arguments: None
*
* Side Effect: None
*
* Returns:
*/
Person::~Person(void) {
// Return memory occupied by the personal name
delete[] personalName;
// Return memory occupied by the family name
delete[] familyName;
}
Dynamic Allocation of Objects (cont.) An Example:
o
o Person *p;
o
Illustration:
o
Dynamic Allocation of Objects (cont.) An Example:
o
o Person *q;
o char *first, *last;
o int age;
o
Illustration:
o
Dynamic Allocation of Objects (cont.) An Example:
o
o first = new char[6];
o last = new char[10];
o age = 26;
o
Illustration:
o
Dynamic Allocation of Objects (cont.) An Example:
o
o strcpy(first, "David");
o strcpy(last, "Bernstein");
o
Illustration:
o
Dynamic Allocation of Objects (cont.) An Example:
o
o q = new Person(first, last, age);
o
Illustration:
o
Dynamic Allocation of Objects (cont.) Returning Memory to the Heap:
o The memory manager doesn't know how many times the object might have requested memory from the heap in its various methods
o The object must keep track of this itself
Destructor:
o A method with the job of returning all "supplemental" memory used by an object
o Has the same name as the class but preceeded by a tilde (i.e., the ~ character)
o Whenever the delete operator is applied to a pointer to an object the object's destructor
is called
Dynamic Allocation of C Strings Recall:
o Strings (in C) are just arrays of characters terminated with a '\0'
An Example:
o
o char *s;
o
o s = new char[20];
o
Dynamic Allocation of C Strings (cont.) A Static Array of Dynamically Allocated Strings:
o
o char *names[4];
o int nameLength;
o
o nameLength = 80;
o
o for (int i=0; i<4; i++) names[i] = new char[nameLength];
o
o strcpy(names[0],"Alice");
o strcpy(names[1],"Bob");
o strcpy(names[2],"Carol");
o strcpy(names[3],"Dan");
o
Dynamic Allocation of Arrays of Objects An Example:
o
o int numWeights;
o Weight *w;
o
o numWeights = 50;
o
o w = new Weight[numWeights];
o
Interpretation:
o w is a pointer to the array
o Each element of w is a Weight object (not a reference to a Weight)
o Each Weight is constructed using the default constructor
An Aside on main So Far:
o Our main function has had no parameters
Now:
o We can discuss a version of main that is passed command-line arguments
o int main(int argc, const char *argv[])