Tom Kelliher, CS18
Apr. 22, 1996
Recall:
The rvalue of a pointer variable of type T is the lvalue of a variable of type T.
Consider the trivial example:
int i; int j; int* pi = &i; // sets pi's rvalue to i's lvalue *pi = 1; // sets i to 1 pi = &j; // sets pi's rvalue to i's lvalue *pi = 2; // sets j to 2
Assume:
Valid assignments:
Which of the assignments are valid/invalid?
int i; int j; char c; double x; int* ip; char* cp; float* fp; ip = &i; cp = NULL; ip = cp; ip = j; fp = &x; cp = &i; cp = (char*)&i; cp = &c; cp += 12; cp *= 2;
The most common mistake with pointer parameters:
void f(int *ip) { *ip = 0; } void g(void) { int i; f(i); }What error message from compiler?
Most common ``fix?''
Variable attributes:
Lifetime example:
int* makeInt(void) { int* pi; pi = new int; assert (pi != NULL); return pi; } // pi just went out of scope, but not the "new int"
AKA heap segment
Two operators:
<type> can be any type --- primitive, derived, or even a class
Examples:
int* pi; pi = new int; // allocate a single int *pi = 0; // modify the new int delete pi; // de-allocate *pi = 0; // design error to reference de-allocated memory delete pi; // *serious* design error pi = new int[10]; // allocate int array pi[1] = 3; delete [] pi; // [] necessary to ensure proper de-allocation // of array pi = NULL; // good programming practice delete pi; // no damage // allocate a struct employeeRecord* employee = new employeeRecord; employee = NULL; // memory leak
Relevant points:
This code is available from the CS18 home page.
client code:
#include <iostream.h> #include "array.h" int main() { IntArrayClass array(10); // array has 10 elements, all zero'ed int i; for (i = 0; i < array.size(); i++) // fill the array array.set(i, i); for (i = 0; i < array.size(); i++) // print cout << array.read(i) << endl; array.resize(20); // 10 new elements for (i = 0; i < array.size(); i++) // print the enlarged array cout << array.read(i) << endl; array.resize(5); // shrink the array for (i = 0; i < array.size(); i++) // print cout << array.read(i) << endl; return 0; }
array.h:
class IntArrayClass { public: IntArrayClass(int size); ~IntArrayClass(void); int size(void); int read(int index); void set(int index, int value); int resize(int newSize); private: int elems; int *ia; };
array.cc:
#include <assert.h> #include <stdlib.h> #include "array.h" // construct an int array with size elements, zero them IntArrayClass::IntArrayClass(int size) { int i; assert (size >= 0); elems = size; ia = new int[elems]; assert (ia != NULL); for (i = 0; i < elems; i++) ia[i] = 0; }
// de-allocate an array IntArrayClass::~IntArrayClass(void) { delete [] ia; ia = NULL; } // return number of elements in array int IntArrayClass::size(void) { return elems; } // return value of one element of the array int IntArrayClass::read(int index) { assert (0 <= index && index < elems); return ia[index]; } // set value of one element of the array void IntArrayClass::set(int index, int value) { assert (0 <= index && index < elems); ia[index] = value; }
// make the array larger or smaller // making it smaller truncates elements from the end // making it larger adds new 0 elements to the end int IntArrayClass::resize(int newSize) { int *ta; int i; int limit; assert (newSize >= 0); // allocate space for the new array, which may be larger *or* smaller // than the old array ta = new int[elems]; assert (ta != NULL); // determine point at which to stop copying elements from old array // to new array limit = (elems < newSize) ? elems : newSize; for (i = 0; i < limit; i++) // copy elements ta[i] = ia[i]; // zero the enlarged part of the array, if necessary for ( ; i < newSize; i++) ta[i] = 0; delete [] ia; // delete old array ia = ta; // "remember" new array elems = newSize; }