New and Delete Operators in C++ with Examples

Dynamic memory allocation in C++ by using the new and delete operators is an essential concept for developing effective and reliable programs. These operators allow memory to be allocated and freed at runtime, but incorrect usage and careless programming can create memory leaks, segmentation fault errors, and undefined behavior. In this blog, we will discuss new and delete operators in C++, including relevant code examples, how to use new and delete in C++, best practices, and mistakes to avoid.

Table of Contents:

Introduction to Dynamic Memory Allocation in C++

Dynamic memory allocation in C++ means allocating memory at run time. This is particularly convenient when the size of a data structure (such as an array) is not known beforehand. In contrast, static memory allocation occurs at compile time with fixed sizes, such as for global or local variables.

Note: Static allocation occurs during compile time (e.g., global or local variables), while dynamic memory is managed via pointers. Memory can be allocated and deallocated during runtime using operators like new and delete.

How to Use the new Operator in C++

In C++, the new operator is used to allocate memory dynamically. It returns a pointer to the start of the allocated memory block. If you declare a single variable with new, C++ will automatically call the object’s constructor, if it is a class type.

Example: 

Cpp

Output: 

new operator in cpp

This code uses new to allocate memory for a single integer. It stores the value 50 into that memory and prints it. At last, to free the allocated memory, the delete is used. 

Allocate a Block of Memory (Array)

To allocate memory for an array, you can use the new operator with square brackets:

Example: 

Cpp

Output:

Allocate a Block of Memory using new operator in cpp

Allocates an array of 5 integer elements using dynamic memory allocation in C++. Loop is used to populate and print the values in the array. Finally, to free the allocated memory, the delete is used. 

Using the delete Operator in C++

You use the delete operator to deallocate that memory, which was allocated with the new operator. 

Example:

Cpp

Output: 

delete operator in cpp

The above code demonstrates the dynamic memory allocation for both single values and arrays. The delete [] operator shows the proper cleanup to avoid memory leaks in C++.

Handling Memory Allocation Failures in C++

When new fails, it means that the system is unable to provide the requested amount of memory (because it simply does not have enough resources) and it throws an std::bad_alloc exception. You can do this with try-catch blocks:

Example: 

Cpp

Output: 

What if Enough Memory is Not Available During Runtime

This code demonstrates two ways to handle memory allocation failure in C++, using a try-catch block to catch std::bad_alloc exceptions and using std::nothrow to prevent exceptions and check for a null pointer instead.

Common Memory Management Errors in C++

Here’s a list of common C++ memory management errors associated with dynamic memory allocation in C++:

  1. Memory Errors: The errors are caused by accessing deleted memory.
  2. Memory Leaks: Memory leaks in C++ occur when memory is allocated but never deallocated.
  3. Double Deletion: If you delete a pointer more than once, the behaviour is undefined.
  4. Invalid Delete: Using delete on memory that was not allocated using new, or delete[ ] when it was allocated by new, and vice versa.
  5. Mixing malloc()/free() with new/delete: Leads to undefined behaviour due to incompatible allocation mechanisms.

Let’s discuss some of the most common C++ memory management errors in detail that are associated with dynamic memory allocation in C++ with examples:

1. Dangling Pointers

A dangling pointer is a pointer that points to a memory location that is already free. Dereferencing such pointers results in undefined behaviour:

Example: 

Cpp

Output: 

1. Dangling Pointers

This can be best understood with the help of the above code that allocates memory using new for an integer and assigns the value 10. After calling delete, the pointer ptr is now a dangling pointer, because it still holds the address of the memory that has been freed. 

2. Memory Leaks

Memory leaks in C++ occur when memory allocated using new is not properly deallocated using delete. This leads to wasted memory, especially for longer-running programs or loops, as the unreleased memory is not available to the system to be reused.

Example:

Cpp

Output: 

2. Memory Leaks in C++

In the above example, the new int[100] allocates the memory on the heap, but the delete[] ptr is missing; Hence, there is no chance of the memory getting released. This may lead to a memory leak.

3. Mixing new/delete with malloc()/free()

  1. malloc() is a C standard library function. It allocates some bytes (a specified number of bytes) from the heap, returning a void* (pointer to memory).
  2. It will not invoke constructors in C++. The delete operator in C++ deallocates memory allocated with new, and also calls the object destructor. 
  3. malloc() does not ensure type safety and object lifecycle management in C++, while delete guarantees proper C++ object cleanup. Thus, the reason mixing malloc() and delete is a bad idea is that delete expects memory allocated with new, whereas malloc() allocates memory allocated with malloc() (obviously).
  4. So if you pass malloc() memory to delete, the program won’t delete the space you allocated (hence, undefined behaviour from now on). That is why malloc()/free() should always be coupled together, and new/delete should be coupled together.

Let’s discuss some differences between new/delete operator and malloc()/free() functions for dynamic memory allocation in C++:

Feature new / delete malloc() / free()
Language C++ C (also usable in C++)
Allocates memory Yes Yes
Calls constructor Yes No
Calls destructor Yes No
Type safety Returns a typed pointer Returns void*
Can be overloaded Yes No

Usage in C++:

Cpp

Output: 

3. Mixing new/delete

Dynamically Allocate Memory Using New and Release using delete. Here, in the new MyClass(), memory for the object is allocated, and the constructor is called; The output is “Constructor called”. delete obj; Delete is used to free up the memory and call the destructor, which will print “Destructor called.”

Get 100% Hike!

Master Most in Demand Skills Now!

Usage in C:

C

Output: 

3. Mixing new/delete in C

The above code uses malloc() in C. It checks whether the allocation was successful, assigns values to the arrays, prints them, and frees them to properly clear the memory to avoid memory leaks in C++.

Overloading new and delete for Custom Memory Allocation in C++

In C++, you can overload the new and delete operators to customise the way memory is allocated and deallocated. This allows you to implement custom memory management strategies, such as tracking memory usage, avoiding memory leaks, or optimizing memory allocation for specific use cases. Overloading new and delete can be helpful when you need more control over how memory is handled in your program.

Example:

Cpp

Output: 

Custom Memory Allocation in C++

In C++, you can overload the new and delete operators. By overloading these operators, you will be able to include custom behaviour such as logging memory usage or handling allocation failures. 

Understanding the Rule of Three, Five, and Zero in C++ Classes

In C++, this practice of C++ memory management in classes is called the C++ Rule of Three, C++ Rule of Five, and C++ Rule of Zero. The C++ Rule of Three states that if a class needs a user-defined destructor, copy constructor, or copy assignment operator, it most likely needs all three. Specifically, the C++ Rule of Five expands this concept to also consider the move constructor and move assignment operator, which help to manage the resources efficiently. The C++ Rule of Zero states that you should try and design your classes so that you do not have to create any of these by using RAII and smart pointers to automatically manage the resource.

Example: 

Cpp

Output: 

C++ Memory Management in Classes

When a class allocates dynamic resources, the C++ Rule of Three refers to the need for that class to define a destructor, copy constructor, and copy assignment operator. This prevents shallow copies and also helps to avoid memory leaks in C++.

Alternatives to Manual Memory Management

Here are some alternatives to manual C++ memory management that help you write safer and cleaner code.

1. Smart Pointers (std::unique_ptr, std::shared_ptr)

Smart pointers help in automatic memory management by freeing the resource when it is no longer required by calling delete, among other memory management functions. This helps to avoid memory leaks in C++ and also dangling pointers. Smart pointer abstractions were included in the C++11 standard and are now used in modern C++.

2. RAII (Resource Acquisition Is Initialization)

RAII is a design paradigm in which resources, such as memory, are bound to the lifetime of objects. The destructor of an object is called automatically when it goes out of scope, so the deletion of resources happens automatically. This will result in safer and more efficient resource management.

3. Standard Containers (std::vector, std::string, std::map, etc.)

These standard containers in C++ handle memory internally, and they can grow and shrink according to the user’s needs. You don’t need to deal with the allocation or free memory, just use them as regular objects, and they will handle the rest of the work.

4. Custom Memory Management Libraries

Libraries such as Boost or memory pools can give more efficient memory handling for applications based on performance. These libraries give extra control and also minimize the risk of manual memory errors.

Best Practices for Using new and delete in C++

  • You should always pair every new with a delete to avoid memory leaks in C++.
  • You must use delete[] when deleting arrays allocated with new[] to ensure proper cleanup.
  • You should avoid raw new and delete in modern C++, and prefer smart pointers like std::unique_ptr or std::shared_ptr.
  • You need to initialize pointers after allocation to prevent undefined behavior when accessing them.
  • You should set a pointer to nullptr after deleting it to avoid dangling pointers.
    You must not delete the same pointer twice, as it leads to undefined behavior or crashes.
  • You can use RAII (Resource Acquisition Is Initialization) to manage resources more safely and efficiently.

Conclusion

The allocation is more flexible and can be done at runtime using new and delete when it comes to dynamic memory allocation in C++. All that said, it is important to use them correctly to avoid memory leaks and dangling pointers. To write safer and cleaner code, you can use some advanced techniques like overloading new/delete and following the Rule of Three/Five/Zero. So, by understanding how to use new and delete in C++, you can easily use these operators when you need to allocate memory dynamically.

New and Delete Operators in C++ – FAQs

Q1. What is dynamic memory allocation in C++?

In general, dynamic memory allocation in C++ means allocating memory during execution via the new and delete operators.

Q2. What is the difference between new and malloc()?

new calls constructors and is type-safe, while malloc() is a C function and doesn’t call constructors.

Q3. When should I use delete[] instead of delete?

If you want to allocate the arrays using new[], use delete[].

Q4. What happens if I forget to deallocate memory?

It leads to a memory leak, which can gradually cause performance degradation.

Q5. Can I mix malloc() with delete or new with free()?

No, mixing them will lead to undefined behaviour. Always pair new/delete and malloc/free.

Q6. How to use new and delete in C++?

You can use new and delete in C++ for dynamic memory management. new is used to allocate memory on the heap for an object and returns a pointer to the allocated memory, and delete is then used to deallocate that memory when it’s no longer needed, to avoid memory leaks in C++.

About the Author

Technical Research Analyst - Full Stack Development

Kislay is a Technical Research Analyst and Full Stack Developer with expertise in crafting Mobile applications from inception to deployment. Proficient in Android development, IOS development, HTML, CSS, JavaScript, React, Angular, MySQL, and MongoDB, he’s committed to enhancing user experiences through intuitive websites and advanced mobile applications.

Full Stack Developer Course Banner