In the previous sections we have seen how to reserve a fixed amount of storage for a matrix at the time the code is compiled. Suppose later on we find we want space for a larger matrix. We would have to modify the code, increasing the matrix dimensions, and then recompile it. This extra step is avoided if we allocate space for the matrix dynamically. With dynamical allocation we don't have to decide on any limits to the size when we compile the code. Instead, at run time we ask the operating system to give us the space we need, provided there is enough memory available. The program size in computer memory then grows. Dynamical allocation can use memory more efficiently because one can ask just for the space required, and the space can be released when it is no longer needed.
The simplest method for allocating space dynamically is to wait until after we know the actual size and then declare the matrix using variables as dimensions. Here is a short code excerpt showing how this is done:
Notice that the declarations for
b, must come after the values
n are known. (And we have been careful to get the correct
number of elements for the matrix times vector operation.)
Space for the matrix
a and vectors
b is automatically allocated and it is automatically
released when the those variables go out of scope (i.e. execution
passes back to a calling program or the program terminates.) The
pointer values for
a[i] are exactly
the same as they would be if we had used constants for the dimensions.
You may use this method for arrays that you are passing to a Fortran coded subprogram, provided the function prototype declaration is written in a compatible way. Here is a way to do it following the above example. The prototype declaration should read
n, we have
max = n.
If we are not trying to interface with Fortran, we can use a more elegant way to allocate matrices dynamically in C++ that makes it easy to pass arrays to C++ subprograms. Here is a simple example:
Let us examine the new features of this code.
ncontiguous double precision values. It declares that
xis a pointer and initializes it to be the address of the first one. It does essentially the same thing as the declaration
Next we create the matrix by treating it as
row vectors of length
n each. To make the syntax work
for us, we also create a list of
m pointers that point to
the first value in each row.
mpointers to doubles. And it declares that
ais a pointer to the first of them, which makes its type a pointer to a pointer to a double - hence the two asterisks. Notice that
a[i]is then a pointer to a double. For each
iwe then request space for
ndoubles and initialize
a[i]to be the address of the first one. Altogether we have allocated space for
mpointers to doubles. Notice that
a[i][j]is a double. The valid range for
iis from 0 to
jfrom 0 to
n-1, which is exactly what we want for the matrix.
Notice that although we refer to the matrix element as
a[i][j] the meaning of this expression is a bit different from
what we get with the static declaration double a[MAX][MAX].
With the dynamic allocation we actually have space allocated for the
a[i]. With the static declaration, the compiler
a[i] also points to the first element in
a row, but we have not allocated storage for it.
, we would be deleting space only for the pointers.
There are variations on this theme. Another method allocates the
space in a single block as follows:
nmatrix elements in row
a[i]come immediately after the
nmatrix elements in row
a[i-1]. With this organization we have in effect declared a to be
double a[m][n];and with the rows arranged in the correct sequence, it is permissible to use this matrix with Fortran subprograms in the same way as before. So if your application uses the same array in calls to both C++ and Fortran subprograms, this method is the most elegant one.