To allocate an array of 10 ints, you can say int A[10];
or
int *A = new int[10]
. But what if we want n ints?
int n; n = ... OR cin >> n; int *A; A = new int[n];
|
We had no way to do this before. If we say int A[n];
we get an
error, unless n is a constant. dynamicIntArray.cpp shows
proper use of this new method. Note that deleting this allocated memory is a
little different. We have to tell the compiler that there is an array at the
end of the pointer by saying delete [] A;
.
A member function of a class that is automatically executed when the object is deleted. There are two times that objects are deleted:
delete x;
{ bozo b; ... } <-------- b goes out of scope here
Syntax:
In the class declaration, public part:
~classname(); //no parametersDefinition:
classname::~classname() { ... }
A destructor is needed only if the default destructor does not suffice. What does a default destructor do?
class bozo { ... }; class clown { ... private: bozo b1, *b2; }; clown c;
When c is destroyed, so is c.b1, but not *(c.b2). We'll need a destructor for clown if you want to destroy *(c.b2):
clown::~clown() { delete b2; }
In an array of objects, delete on the array runs the destructor on
the objects in reverse order.
dynamicObjectArray.cpp shows that by printing out the
addresses of the objects as they are created and destroyed. Note also
that the default constructor (the no-parameter constructor) is run on
each object in the array when the array is allocated, and these
default constructors are run in forward order. One very
useful concept shown in this demo is the use of the keyword
this
, which holds the address of the object upon which
the function was invoked.
|
Remember from yesterday that the two portions of memory that grow, the stack and the heap, grow towards each other. It is possible that they may meet. You can deal with this two ways:
NULL
:counter *bozo = new counter[n]; if (bozo == NULL) //out of memory else //OK
setNewHandler()
function
works.
You may have noticed that we've been using dynamic arrays a lot like normal arrays. We can index into them just like any array. The answer for this is an important principle. In C/C++:
The name of an array is a constant pointer to the 0th element.
If we have an array A, then both &A[i]
and
A+i
are the address of the ith element. This works for
an array of any type, including arrays of objects.
So
A[i]
and *(A+i)
are the ith element in array
A. In fact, many compilers internally transform A[i]
to
*(A+i)
.
|
dynamicIntArray2.cpp proves that the two ways of indexing into an array are exactly the same.
Now, remember how I said that arrays are passed "like" by reference? That's because A = A+0 = &A[0]. So when you make a call like
f(A, n);you're actually passing the address of the 0th element of A. And these two are the same:
void f(int A[], int n); void f(int *A, int n);
There's only one real difference - The first way is very uncool. It's the way used by beginning programmers before they learn that the name of an array is a constant pointer to the 0th element. Now that you know that, show it by never again using the first way of writing functions.
To Index Previous Next