Let's finish up basic dynamic multi-dimensional arrays.
What we have is the same picture from last time which represents an
M x N array. It is declared as
int **A;
where A[i] contains the address of the ith row. This
address equals &A[i][0].
We can express the address of the (i,j) entry as &A[i][j] OR A[i] + j
Functions that return pointers
We can have functions that return not only int, doubles, and other stuff
but that return pointers too!
See Demo 2D-array-in-1D.cpp
- This demo simulates a 2-D array in 1-D. Graphically this looks like:
- Function entry returns a pointer to (i,j) entry, given A, i, j, and N.
- Uses row-major ordering.
- Needs N = # of columns.
- Doesn't need M = # of rows.
- Doesn't need leftmost dimension, which is consistent with our previous
array experiences.
- Read declaration as *entry(A, i, j, N) is an int. Therefore entry
(A, i, j, N) is a pointer to an int.
Dynamic Arrays of Pointers
Notice that in Raindrops Ptr.cpp, we could have run a constructor on each
drop as it was allocated:
theDrops[dropCount++] = new drop(center);
What if we wanted a dynamic array of drops? This would look like:
- theDrops[i] is a pointer to a drop.
- theDrops[0] is a pointer to a drop.
- theDrops is a pointer to a pointer to a drop.
We would declare this as drop **theDrops;
.
.
.
int maxDrops = ...;
theDrops = new drop * [maxDrops];
For the life program we will have a 2-D array of ponters to cells. The
cell constructor will have the following definition:
cell::cell(int row, int column);
The colony class will look like public:
colony(int rows, int cols);
~colony();
private:
cell ***cells;
Here is part of the constructor: cells = new cell ** [rows];
for (int r = 0; r < rows; r++) {
cells[r] = new cell * [cols];
for (int c = 0; c < cols; c++)
cells[r][c] = new cell(r, c);
}
Graphically the game of life looks like:
The destructor will be defined as: for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++)
delete cells[r][c];
delete [] cells[r];
}
delete [] cells;
Copying Object Values
What happens when the value of one object is copied into another object?
The answer: It depends! The default action taken, unless
you specify otherwise, which is that all member data is copied. If the
member data is a pointer, the address in that pointer is
copied. The data the pointer is pointing to is not.
See Demo NoCopyConstr.cpp
After intArray T = S; we have:
So changing S's array changes T's array. This is known as shallow
copying.
What we want is deep copying, which looks like this:
Now the changes to S and T are independent from one another. We can get
this effect by using a copy constructor.
See Demo CopyConstr.cpp
- Notice the special copy constructor syntax.
- Invoked when say intArray T = S;
- You never explicitly call a copy constructor. It is called implicitly
whenever:
- One exists for the object being copied.
- And the target of the copy cannot possibly yet exist.
There are three times that a copy constructor is called:
- Declaration with initialization:
intArray T = S;
- Copying actual into formal in call by value:
void bozo(intArray T);
.
.
intArray S(5);
.
.
bozo(S);
- Copying return value back to the caller:
intArray bozo(...)
{
intArray S;
.
.
return S;
}
... bozo(...) ...
To Index
Previous
Next