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;
}