Back to C++
2026-02-286 min read

new and delete (C++)

Learn new and delete (C++) step by step with clear examples and exercises.

Why This Matters

In this extensive guide on new and delete in C++, we aim to provide a comprehensive understanding of these fundamental operators, their practical uses, common pitfalls, and how they can help you tackle real-world programming challenges effectively. Let's look at into the world of dynamic memory allocation!

The Importance of Dynamic Memory Allocation

Dynamic memory allocation is an essential aspect of C++ that allows us to create objects during runtime, providing flexibility when dealing with arrays or complex data structures. new and delete operators are crucial for managing this dynamically allocated memory efficiently. Mastering these operators can help you write cleaner, more efficient code and avoid common pitfalls leading to memory leaks or segmentation faults.

Prerequisites

To fully grasp the concepts covered in this tutorial, you should be familiar with:

  • Basic C++ syntax (variables, functions, loops, etc.)
  • Data structures like arrays and linked lists
  • Understanding of pointers and their usage in C++
  • Familiarity with exception handling (optional but recommended)
  • A basic understanding of classes and objects (if covering constructor and destructor sections)

Core Concept

Allocating Memory with new

The new operator is used to dynamically allocate memory for an object. The general syntax is:

type *ptr = new type;

Here, type represents the data type of the object you want to create, and ptr is a pointer that holds the address of the newly allocated memory. For example:

int *pInt = new int; // Allocates memory for an integer

You can also allocate arrays using new:

int *pArray = new int[10]; // Allocates memory for an array of 10 integers

Deallocating Memory with delete

Once you're done using the dynamically allocated memory, it is crucial to free up that space to avoid memory leaks. The delete operator does this by reversing the allocation process:

delete ptr; // Deletes the memory allocated for an object
delete[] pArray; // Deletes the memory allocated for an array

Placement New and Memory Pools

  1. Placement new: Allows you to specify the exact location in memory where an object should be created. This can be useful when managing custom memory pools or working with specific memory allocators.
  1. Memory pools: Implementing a simple dynamic memory pool can help manage large blocks of memory more efficiently, reducing the overhead associated with frequent calls to malloc and free.

Constructors and Destructors

  1. Constructors: When an object is created using new, its constructor is called automatically. This allows you to initialize the object's state before using it. In a class, constructors can perform various tasks such as initializing member variables or allocating additional memory.
  1. Destructors: When an object is destroyed using delete, its destructor is called automatically. This gives you a chance to clean up any resources acquired during the object's lifetime, such as closing files or freeing allocated memory. In a class, destructors can be used to deallocate dynamically-allocated member variables.

Worked Example

Let's consider an example where we dynamically allocate memory for a linked list:

#include <iostream>
using namespace std;

class Node {
public:
int data;
Node* next;

// Constructor
Node(int d) : data(d), next(nullptr) {}

// Destructor
~Node() {
cout << "Deleting node with data: " << data << endl;
}
};

void push(Node** head_ref, int new_data) {
Node* new_node = new Node(new_data); // Allocate memory for a new node and initialize it with the given data
new_node->next = (*head_ref);
(*head_ref) = new_node;
}

void printList(Node *node) {
while (node != nullptr) {
cout << node->data << " ";
node = node->next;
}
}

int main() {
Node* head = nullptr;

push(&head, 7);
push(&head, 6);
push(&head, 5);

cout << "Created Linked List: ";
printList(head); // Output: Created Linked List: 5 6 7
// The destructor is called automatically when the memory for each node is deallocated

delete head; // Deallocate the memory for the linked list
head = nullptr; // Set head to NULL after deallocation

return 0;
}

In this example, we've added a constructor and destructor to our Node class. The constructor initializes the node with the given data, while the destructor prints a message when the node is deleted.

Common Mistakes

  1. Forgetting to deallocate memory: Failing to call delete or delete[] when you're done with the dynamically allocated memory can lead to memory leaks.
  1. Double-deletion: Deleting already-freed memory will cause a segmentation fault. Be sure to only delete memory once.
  1. Using delete on non-initialized pointers: Attempting to delete uninitialized pointers can lead to undefined behavior and crashes.
  1. Not setting pointers to NULL after deallocation: Setting pointers to NULL after deallocation can help avoid dangling pointers and simplify debugging.
  1. Leaking memory in exception handling: In cases where exceptions are thrown during the execution of a program, make sure to handle them properly and free up any dynamically allocated memory before exiting.
  1. Not initializing member variables in constructors: If you don't initialize member variables in your class constructor, they will remain uninitialized, potentially leading to undefined behavior.
  1. Calling delete on a pointer that points to an array: When deleting an array, use delete[] instead of delete.

Practice Questions

  1. Write a function that dynamically allocates an array of n integers and returns a pointer to its first element.
  1. Implement a simple dynamic memory pool for managing large blocks of memory in your program.
  1. What happens if you forget to initialize the pointers before using them with new or delete?
  1. Write a function that uses placement new to create an object at a specific location in memory.
  1. Implement a destructor for the Node struct from our linked list example, which frees any dynamically allocated member variables within the node when it is deleted.
  1. What are some common mistakes to avoid when using constructors and destructors with dynamic memory allocation?

FAQ

  1. Why can't I use delete on non-initialized pointers?

Using delete on uninitialized pointers leads to undefined behavior, as the pointer may not point to any valid memory location.

  1. Is it necessary to set pointers to NULL after deallocation?

While not strictly necessary, setting pointers to NULL after deallocation can help avoid dangling pointers and simplify debugging.

  1. What is the difference between new[] and new?

new allocates memory for a single object, while new[] allocates memory for an array of objects. Correspondingly, you should use delete or delete[] to deallocate the memory accordingly.

  1. What is placement new, and how can it be useful?

Placement new allows you to specify the exact location in memory where an object should be created. This can be useful when managing custom memory pools or working with specific memory allocators.

  1. Why are constructors and destructors important when using new and delete?

Constructors and destructors provide a way to initialize and clean up resources for objects created and destroyed using new and delete, ensuring that your program behaves correctly and efficiently.

  1. What is the difference between delete and delete[] when deleting an array?

delete[] should be used to deallocate memory allocated with new[]. It properly iterates through the allocated memory and calls the destructors (if applicable) for each element, followed by freeing the memory. Using delete on an array will only free the first element of the array.

  1. What happens if I forget to initialize member variables in a class constructor?

If you don't initialize member variables in your class constructor, they will remain uninitialized, potentially leading to undefined behavior or runtime errors.

new and delete (C++) | C++ | XQA Learn