new and malloc() can both allocate dynamic memory, but they are not equivalent.
malloc() and free() are the library functions provided by the C which can be used to allocate and deallocate memory at runtime, whereas new and delete are the operators provided by C++ which can be used to allocate and deallocate memory at runtime.
The basic difference between new and malloc() is that memory allocation using new allocates storage and calls the constructor which initializes the memory. In case of malloc(), returned memory is uninitialized and needs to be initialized explicitly.
Similarly, deallocating memory using delete calls the destructor and hence allowing to do a proper cleanup whereas in case of free(), destructors are not called and hence cleanup needs to be done prior free() call.
For normal C++ application code, prefer automatic storage, standard containers, and smart pointers where possible. Use malloc() mainly when working with C APIs or low-level memory-management code.
Let’s look into some more difference between these functions.
new/delete vs malloc()/free() at a glance
| Feature | new/delete | malloc()/free() |
|---|---|---|
| Part of | C++ language | C standard library |
| Allocation size | Determined from the type | Specified manually in bytes |
| Return type | returns a pointer of the requested type | malloc() returns void*; conversion is required in C++ |
| Allocation failure | In case of error, exception (normally std::bad_alloc) is thrown. | In case of error, NULL pointer is returned. |
| Size calculation | Memory size is automatically calculated by the compiler. | Memory size needs to be passed explicitly. |
| Arrays | Arrays can be handled easily (by using new[] and delete[]). | User has to handle arrays by themselves. |
| Reallocation | Reallocation needs to be handled by the User. | Reallocation can be done easily using realloc(). |
| Overriding | can be overloaded or replaced | Can’t override these functions. |
| Constructor/Destructor calling | Constructor/Destructor is always called. | Constructor/Destructor are not called. |
What does new do in C++?
The new expression does two important things:
- obtains enough storage for the requested object;
- initializes the object in that storage.
#include <iostream>
class Employee
{
public:
Employee()
{
std::cout << "Constructor called\n";
}
~Employee()
{
std::cout << "Destructor called\n";
}
};
int main()
{
Employee* employee = new Employee;
delete employee;
return 0;
}
Output
Constructor called
Destructor called
new Employee allocates storage and constructs an Employee object.delete employee destroys the object and then releases its storage
What does malloc() do?
malloc() is defined in <cstdlib> and allocates a requested number of bytes.
#include <cstdlib>
int main()
{
int* number = static_cast<int*>(std::malloc(sizeof(int)));
if (number != nullptr)
{
*number = 10;
std::free(number);
}
return 0;
}
Unlike new, malloc() does not call a class constructor or otherwise initialize the allocated storage for you. If allocation fails, it returns a null pointer
Does new use the free store while malloc uses the heap?
You may sometimes see the claim that:
newallocates from the “free store”;malloc()allocates from the “heap”.
It is better not to rely on that distinction.
C++ language doesn’t require new and malloc() to use different physically separate memory areas. In fact, it is very much possible that an over-ridden implementation of new may internally use malloc().
What happens when allocation fails?
A normal throwing new expression throws std::bad_alloc if allocation fails.
There is also a std::nothrow form of new that can return nullptr.
try
{
int* values = new int[1000000];
delete[] values;
}
catch (const std::bad_alloc&)
{
// Allocation failed
}
malloc() returns nullptr when it cannot allocate the requested storage.
int* values =
static_cast<int*>(std::malloc(1000000 * sizeof(int)));
if (values == nullptr)
{
// Allocation failed
}
new[] vs malloc() for arrays
With new[], C++ calculates the storage requirement from the element type whereas with malloc(), user calculate the number of bytes themselves
For class arrays, new[] also constructs the elements, and delete[] destroys them.
int* numbers = new int[10];
delete[] numbers;
int* numbers =
static_cast<int*>(std::malloc(10 * sizeof(int)));
std::free(numbers);
Can you mix new with free()?
No, we should not do that.
- Storage obtained from a
newexpression must be released using the matchingdeleteform. - Storage obtained from
malloc()must be released usingfree(). - Passing memory to a mismatched deallocation mechanism results in undefined behavior. C++ requires
delete/delete[]to operate on storage obtained from corresponding allocation mechanisms.
The correct pairs to be used are:
new -> delete
new[] -> delete[]
malloc() -> free()
Class object example: new/delete vs malloc/free
Let’s look into an example to understand the differences better.
class Base
{
public:
int a;
char b;
Base (int a, char c);
~Base ();
};
Base::Base (int a, char c): a(a), b(c)
{
std::cout << "Inside Constructor" << std::endl;
}
Base::~Base ()
{
std::cout << "Inside Destructor " << std::endl;
}
int main ()
{
std::cout << "Calling New" << std::endl;
Base* using_new = new Base(4,'n');
std::cout << "Calling Malloc" << std::endl;
Base* using_malloc = (Base*) malloc (sizeof (Base));
std::cout << "Calling Delete" << std::endl;
delete using_new;
std::cout << "Calling free" << std::endl;
free (using_malloc);
}
Let’s analyze the output of the above program.
Calling New
Inside Constructor
Calling Malloc
Calling Delete
Inside Destructor
Calling free
Summary
Key differences are
newis a C++ operator.malloc()is a C library function.newknows the type being allocated.malloc()works with a raw byte count.newnormally throws on allocation failure.malloc()returnsnullptr.newmust be matched withdelete.malloc()must be matched withfree().
For modern C++ code, prefer standard containers and smart pointers whenever possible instead of managing dynamic memory manually.