22B. Creating and Destroying Arrays

Creating an array in the run-time stack

Statement
  int A[10];
creates an array of ints within the current function's run-time stack frame and names it A. In general, the form is
  T name[size];
where T is the type of each variable in the array, name is the array's name and size is the number of items. For example,
  double stuff[100];
creates an array called stuff of size 100, where each variable in the array has type double.

Creating an array in the heap

If you want to use an array after the function that created it returns, allocate that array in the heap, not in the run-time stack. Expression new T[size] allocates a new array with size variables in it, each of type T.

Remember that an array is treated just like a pointer to the first thing in a chunk of memory. So expression new int[25] has type int*. Statement

  int* A = new int[25];
allocates a new chunk of 25 ints and stores a pointer to the first one of those ints into variable A.

The size can be given by any expression that yields an integer. For example, if you already have an integer variable called n that currently holds 50, then

  double* B = new double[n];
allocates a chunk of 50 doubles.


Watch out: new int(25)

To allocate an array, use square brackets around the size. Unfortunately, expression new int(25) allocates one variable and stores 25 in it. That is really not a good language feature, but we have to live with it and watch out for it.

delete [ ] p;

If you allocate an array (using brackets with new), then, when you delete that array, write an empty set of square brackets after delete. It is up to you to know whether you are deallocating an array of just one thing.

Watch out: delete an entire array

Never try to delete just a part of an array. Your only option is to delete the entire array. If you try to delete part of an array, you will corrupt the heap manager.

Watch out: never delete an array that is in the run-time stack

You only delete an array that is in the heap. If you do
  int A[100];
  ...
  delete [] A;
you will corrupt the heap manager.

Watch out: do not misuse the run-time stack

Consider the following attempt to allocate an array.
  int* allocArr(int n)
  {
    int A[n];
    return A;
  }
The compiler will not give you an error on this. A is an array of integers (type int*), so the correct type of thing is returned. But the returned pointer is pointing into the stack frame of allocArr. As soon as allocArr returns, that becomes a dangling pointer. To allocate an array that you need to keep using after the function returns, use new.

Fixed array sizes should be named constants

The preceding example creates arrays of size 10 and 100. But if you need to create an array of a fixed size, always make the size a named constant. For example, write
  const int nameMax = 100;
and, to create an array, write
  char name[nameMax];
You want to have a single point of modification. Wherever you need to refer to nameMax, write nameMax, not 100. If you decide to change nameMax to 200, you should only need to change the line that defines constant nameMax.


Summary

In C++, you can create an array either in the frame of the current function or in the heap. Use expression new int[n] to allocate an array of n integers in the heap. Its value is the address of the first of those integers, so new int[n] has type int*.

To delete an array A that was allocated in the heap, say

  delete [] A;

If you do not know how large an array needs to be, make its size a named constant so that the size is easy to change by changing the value of that constant.


Exercises

  1. Write a statement that allocates a new array of 75 characters called frog. The new array should be in the heap. Answer

  2. There is something wrong with the following function. Explain what is wrong.

      // makeZeroedArray(n) returns an array with
      // n items, all set to 0.
    
      int* makeZeroedArray(int n)
      {
        int A[n];
        for(int i = 0; i < n; i++)
        {
           A[i] = 0;
        }
        return A;
      }
    
    Answer

  3. There is something wrong with the following function. Explain what is wrong.

      // makeZeroedArray(n) returns an array with
      // n items, all set to 0.
    
      int* makeZeroedArray(int n)
      {
        int* A = new int(n);
        for(int i = 0; i < n; i++)
        {
           A[i] = 0;
        }
        return A;
      }
    
    Answer

  4. Suppose array A has been created by

      double* A = new double[m];
    
    If you are done with array A and want to return it to the heap manager, what statement should you use? Answer

  5. Suppose array A has been created by

      double A[m];
    
    When the program is done with array A, what should the program do? Answer

  6. The following function tries to read up to 100 integers from the standard input. So it allocates an array of size 100. But that is wasteful if you only actually read a few integers before hitting the end of the file. So this function decides to give the unused portion of the array back to the heap manager. Does that work?

      int* readInts()
      {
        int* A = new int[100];
        int i;
    
        for(i = 0; i < 100; i++)
        {
          int k = scanf("%i", &(A[i]));
          if(k != 1)
          {
            break;
          }
        }
    
        if(i < 100)
        {
          delete [] A + i;
        }
    
        return A;
      }
    
    Answer

  7. Function readInts() above wants to read some numbers and return an array containing them. If the bad part is removed from it, how would its caller know how many integers were read? Answer

  8. What is the type of expression new long[12]? Answer

  9. There is something wrong with the following function. Explain what is wrong.

      // makeZeroedArray(n) returns an array with
      // n items, all set to 0.
    
      int* makeZeroedArray(int n)
      {
        int* p = new int[n];
        for(int i = 0; i < n; i++)
        {
           p[i] = 0;
        }
        delete [] p;
        return p;
      }
    
    Answer

  10. There is something wrong with the following function. Explain what is wrong.

      // makeZeroedArray(n) returns an array with
      // n items, all set to 0.
    
      int* makeZeroedArray(int n)
      {
        int* p = new int[n];
        for(int i = 0; i <= n; i++)
        {
           p[i] = 0;
        }
        return p;
      }
    
    Answer