A test
Here’s the old test program for
Stash rewritten for the PStash:
//: C13:PStashTest.cpp
//{L} PStash
// Test of pointer Stash
#include "PStash.h"
#include "../require.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
PStash intStash;
// 'new' works with built-in types, too. Note
// the "pseudo-constructor" syntax:
for(int i = 0; i < 25; i++)
intStash.add(new int(i));
for(int j = 0; j < intStash.count(); j++)
cout << "intStash[" << j << "] = "
<< *(int*)intStash[j] << endl;
// Clean up:
for(int k = 0; k < intStash.count(); k++)
delete intStash.remove(k);
ifstream in ("PStashTest.cpp");
assure(in, "PStashTest.cpp");
PStash stringStash;
string line;
while(getline(in, line))
stringStash.add(new string(line));
// Print out the strings:
for(int u = 0; stringStash[u]; u++)
cout << "stringStash[" << u << "] = "
<< *(string*)stringStash[u] << endl;
// Clean up:
for(int v = 0; v < stringStash.count(); v++)
delete (string*)stringStash.remove(v);
} ///:~
As before, Stashes are created and
filled with information, but this time the information is the pointers resulting
from new-expressions. In the first case, note the line:
intStash.add(new int(i));
The expression new int(i) uses the
pseudo-constructor form, so
storage for a new int object is created on the heap, and the int
is initialized to the value i.
During printing, the value returned by
PStash::operator[ ] must be cast to the proper type; this is repeated for
the rest of the PStash objects in the program. It’s an undesirable
effect of using void pointers
as the underlying representation
and will be fixed in later chapters.
The second test opens the source code
file and reads it one line at a time into another PStash. Each line is
read into a string using
getline( ), then a new string
is created from line to make an independent copy of that line. If we just
passed in the address of line each time, we’d get a whole bunch of
pointers pointing to line, which would only contain the last line that
was read from the file.
When fetching the pointers, you see the
expression:
*(string*)stringStash[v]
The pointer returned from operator[
] must be cast to a string* to give it the proper type. Then the
string* is dereferenced so the expression evaluates to an object, at
which point the compiler sees a string object to send to
cout.
The objects created on the heap must be
destroyed through the use of the remove( ) statement or else
you’ll get a message at runtime telling you that you haven’t
completely cleaned up the objects in the PStash. Notice that in
the case of the int pointers, no cast is necessary because there’s
no destructor for an int and all we need is memory
release:
delete intStash.remove(k);
However, for the string pointers,
if you forget to do the cast you’ll have another (quiet) memory leak, so
the cast is essential:
delete (string*)stringStash.remove(k);
Some of these issues (but not all) can be
removed using templates (which you’ll learn about in Chapter
16).