CS 70

The delete Keyword

  • LHS Cow speaking

    We can allocate memory whenever we want on the heap.

  • RHS Cow speaking

    In exchange, we have to make sure to deallocate that memory when we are done with it.

You may recall that the new keyword

  • Allocates memory on the heap;
  • Initializes the new thing; and,
  • Returns a pointer to the new thing.

The opposite of new is the delete keyword, which operates in reverse; it

  • Takes a pointer to something on the heap;
  • Destroys that thing; and,
  • Deallocates the memory at that address.

For example,

void existentialMoo(size_t numSpots, size_t age) {
    Cow* c = new Cow{numSpots, age};  // "They give birth astride of a grave,
    c->moo();                         //  the light gleams an instant,
    delete c;                         //  then it's night once more."
                                      // - Samuel Beckett (Waiting for Godot)
}

int main() {
    existentialMoo(4, 2);
    return 0;
}

Key Points:

  • delete is better read as "delete the thing in memory at ________".
    • You give it the address of the thing that should be deallocated.
  • Nothing happens to the pointer that you give to delete.
    • It even still points to the now deallocated memory!
    • Be careful!
  • When you are about to lose your last pointer to something, use that pointer to delete it!

In other words, when you write delete cowPtr;, in your head don't say “delete cowPtr”, say “delete the Cow at cowPtr”.

  • LHS Cow speaking

    Hey, Dog, what is the shortest-lived object on the heap?

  • Dog speaking

    I don't know, what is the shortest-lived object on the heap?

  • LHS Cow speaking

    It's

    delete new Cow*{4, 2};
    
  • Dog speaking

    Oh. I thought that was the setup for a joke.

  • LHS Cow speaking

    Nope, just an illustration that delete takes the same address that new returns!

Deleting Arrays

We have a special keyword for deleting arrays: delete[].

This form is important, because it informs the compiler that the pointer does not only point to one thing, but to an entire array.

That way the compiler knows it should destroy and deallocate everything in the array!

A delete For Every new

In order to prevent memory leaks, your program must perform exactly one delete for every new that it performs.

Make sure that you use the matching operators:

  • newdelete
  • new...[]delete[]

The delete statement needs to take the same address that the new statement returned.

  • RHS Cow speaking

    Here's a good rule of thumb: always know when something on the heap will be deleted.

  • LHS Cow speaking

    Whenever you use new, identify where in the code that thing will be deleted and what variable will hold the address.

  • RHS Cow speaking

    Then go ahead and write that delete statement!

  • LHS Cow speaking

    That way whether you should use delete or delete[] is fresh in your mind, and you are less likely to forget to do it!

Practice

Consider this program:

double fileMedian(string filename) {
    std::ifstream fin{filename};

    // First line has the number of datapoints
    size_t numDatapoints;
    fin >> numDatapoints;

    double* data = new double[numDatapoints];
    for (size_t i = 0; i < numDatapoints; ++i) {
        fin >> data[i];
    }

    // This is a real thing that you can actually do!
    // (it requires the <algorithm> header)
    std::sort(data, data + numDatapoints);

    double median;
    if (numDatapoints % 2 == 1) {
        // Return the middle element
        median = data[numDatapoints/2];
    } else {
        // Return the average of the middle 2 elements
        median = (data[numDatapoints/2 - 1] + data[numDatapoints/2])/2;
    }

    return median;
}

int main() {
    std::cout << fileMedian("data.txt") << std::endl;
    return 0;
}

Assume that data.txt has 2 on the first line and then two datapoints, 1.0 and 2.0. Now trace this program using a memory diagram.

(Really do it!)

(No, really! This is an important skill to practice.)

Write the delete statement necessary to prevent a memory leak and specify where in the code it should go.

The line of code:

Where should it go?

Key Points:

  • Memory diagrams can really help prevent memory leaks!
  • If you are crossing out the last name of something on the heap, and it hasn't been deallocated, it is about to leak.
    • Put a delete statement right there!
  • The diagram can also help you determine which variable to give to delete.
    • It's the variable that contains the address of the thing to destroy and deallocate.

(When logged in, completion status appears here.)