Skip to Content
Course content
Click on the "Edit" button in the top corner of the screen to edit your slide content.

A few years ago, I was reviewing code for a junior dev who had built a fancy particle system for a small indie game. The visuals were stunning, but there was a problem: the game would run perfectly for about twenty minutes, and then the frame rate would tank until the entire OS froze. When we looked at the task manager, the application was eating 12GB of RAM and still climbing. He was calling new Particle() every time a spark flew from an explosion, but he'd forgotten to ever call delete. He had created a "memory leak"—a slow-motion train wreck where the program claims memory from the system but never gives it back, effectively starving every other process on the machine.

Claiming Your Slice of the Heap

Up until now, we've mostly dealt with automatic memory. When you declare int x = 10; inside a function, that variable lives on the stack. It's fast, and it disappears the moment the function returns. But the stack is limited, and more importantly, you can't decide at runtime how much space you need. If you don't know if your user is going to upload ten images or ten thousand, the stack won't cut it.

This is where new comes in. When you use new, you're asking the operating system for a chunk of memory on the "heap." The heap is a massive pool of memory available to your program. Because the system doesn't know when you're finished with this memory, new doesn't return a value; it returns a pointer to the address of the allocated space. I always tell people to think of new as a contract: the system gives you the memory, but you are now legally responsible for it until the end of time (or until the program terminates).

int* myDynamicInt = new int; // Allocate one integer on the heap
*myDynamicInt = 42;            // Use it like any other pointer

The Obligation of the Delete Operator

The contract I mentioned earlier is where most C++ bugs are born. Unlike Java or Python, C++ has no garbage collector. There is no "cleanup crew" coming behind you to pick up the trash. If you call new, you must eventually call delete. If you lose the pointer to that memory before you delete it—say, by letting the pointer variable go out of scope—that memory is "leaked." It's still reserved by your program, but you no longer have the address to find it or free it.

To fulfill your end of the bargain, you use the delete operator. This tells the system, "I'm done with the memory at this address; feel free to give it to someone else."

delete myDynamicInt;     // Free the memory
myDynamicInt = nullptr;     // Good practice: prevent "dangling pointers"

I highly recommend setting your pointer to nullptr immediately after deleting it. There is nothing more frustrating than a "use-after-free" bug, where you accidentally try to read memory you've already given back to the OS, leading to crashes that are incredibly hard to debug.

The Danger of the Square Bracket Mismatch

Things get slightly more complex when you need to allocate an array. If you need a block of memory for multiple items, you use new[]. This is common when you're implementing your own data structures or handling raw binary buffers.

int size = 100; 
int* myArray = new int[size]; // Allocate an array of 100 integers

Here is the part that trips up almost everyone at first: you cannot use the standard delete to clean this up. You must use delete[]. If you use the single-object delete on an array, you're invoking undefined behavior. On some systems, it might work; on others, it will crash instantly; and on some, it will only delete the first element of the array and leak the rest. Always match your brackets: new pairs with delete, and new[] pairs with delete[].

delete[] myArray; // Correctly frees the entire array



📋 Practical Task

Exercise: Building a Dynamic String Buffer

Your task is to simulate a simple text buffer that can grow based on user input. Since we are focusing on new and delete, you will implement this manually without using std::string or std::vector.

Write a program that does the following:

  • Asks the user how many characters they wish to store in a message.
  • Uses new char[] to allocate exactly that amount of memory (plus one extra byte for the null terminator '\0').
  • Uses std::cin.getline() to read the user's message into that buffer.
  • Prints the message back to the user.
  • Correctly frees the memory using delete[] before the program exits.

Bonus challenge: Wrap this logic in a way that ensures memory is deleted even if the user enters an invalid size (like a negative number).

Rating
0 0

There are no comments for now.

to be the first to leave a comment.