CS 70

Elephant Parade, Part 3: Dynamically Allocated Arrays

  • Goat speaking

    Meh. We still haven't solved the problem.

  • LHS Cow speaking

    Which problem is that?

  • Goat speaking

    Five Elephants still isn't a parade!

  • LHS Cow speaking

    Well, we can make the maximum bigger now, if we want.

  • Goat speaking

    There shouldn't be a maximum! The user should be able to have as long a parade as they want!

  • LHS Cow speaking

    You're right. Let's try a different approach.

Dynamically Allocated Arrays

We've talked about statically sized arrays on the stack. Statically sized means that we know the size of the array at compile time.

Why do we need to know array sizes at compile time?

We need to know the size of arrays on the stack, because the entire array is contained within the stack frame.

The compiler needs to be able to figure out how big the stack frame is for each function so that the right amount of memory is allocated when the function is called.

But we don't have that problem on the heap! Heap memory is allocated whenever we want. The compiler doesn't have to know beforehand how much to allocate. Whenever we want heap memory, however much we want, we just ask for it.

Key Point: When you allocate an array on the heap, you can use a non-constexpr variable as the array size!

For example, if you want to get the array size from the user, you can't say;

size_t numElements;
cin >> numElements;
int arr[numElements]; // ERROR! numElements is not a compile-time constant!

but this version will work:

size_t numElements;
cin >> numElements;
int* arr = new int[numElements];

Key ideas:

  • You can allocate an array on the heap using new...[].
  • The address that is returned is the address of the first element of the array.
    • So you can use indexing notation as usual.
  • The array isn't placed inside our stack frame, so the size of the array can be given by a variable!

As Many Elephants As You Want

  • RHS Cow speaking

    Now we can choose the size of an array based on what happens during execution.

  • LHS Cow speaking

    So we can make the array as big as the user wants!

Here's a new version of the Elephant Parade example code. We've changed it so that it

  • Asks the user for the number of Elephants at the beginning.
  • Allocates an array of the given number of Elephant objects (not pointers).
    • We've left this part blank for now.
  • Prompts the user for information about each Elephant.
int main() {
    size_t numElephants;
    cout << "How many elephants will parade? ";
    cin >> numElephants;
    ////////////////////////////////////////////////////
    // Allocate an array of numElephants Elephant objects
    ////////////////////////////////////////////////////

    for (size_t i = 0; i < numElephants; ++i) {
        cout << "Please enter elephant " << i << endl;

        string name;
        cout << "Name: ";
        cin >> name;

        int age;
        cout << "Age: ";
        cin >> age;

        Elephant el{name, age};
        elephants[i] = el;
    }

    // We'll just assume this works
    sortElephantsByName(elephants, elephants + numElephants);

    cout << "The elephants are parading!" << endl;

    for (size_t i = 0; i < numElephants; ++i) {
        cout << elephants[i].getName() << " (" << elephants[i].getAge() << ")" << endl;
    }

    return 0;
}

Write the missing line of code to allocate the array of Elephant objects.

Answer:

Elephant* elephants = new Elephant[numElephants];
  • RHS Cow speaking

    Let's quickly walk through this version to see what it looks like in memory.

(When logged in, completion status appears here.)