Question
In C++, there are multiple ways to allocate and free memory. I understand that if you call malloc, you should later call free, and if you use the new operator, you should pair it with delete. I also know that mixing them is a mistake—for example, calling free() on memory created with new.
However, I am not sure when to use malloc/free versus new/delete in real-world C++ programs.
What rules of thumb or conventions do experienced C++ developers follow when deciding between them?
Short Answer
By the end of this page, you will understand the difference between malloc/free and new/delete in C++, why new is usually preferred over malloc for C++ objects, and why modern C++ often avoids both in favor of RAII and standard library containers such as std::vector, std::string, and smart pointers.
Concept
malloc and free come from C. new and delete are part of C++.
The key difference is that C++ objects are more than raw memory.
What malloc does
malloc:
- allocates a block of raw memory
- returns a pointer to that memory
- does not call constructors
- does not know about C++ object lifetime
int* p = (int*)std::malloc(sizeof(int));
if (p) {
*p = 42;
std::free(p);
}
This works for simple memory, but malloc does not create a real C++ object in the full language sense for class types.
What new does
new:
- allocates memory
- constructs an object in that memory
- returns a correctly typed pointer
:
Mental Model
Think of memory like an empty apartment.
mallocgives you the apartment space, but it does not bring in furniture, set up electricity, or make it livable.newgives you the apartment space and moves the object in properly.deletemoves the object out properly and cleans things up.freeonly releases the apartment space.
For simple raw bytes, an empty apartment may be enough. For real C++ objects, you usually need the full move-in and move-out process.
A class constructor is like setup instructions. A destructor is like cleanup instructions. malloc and free ignore those instructions.
Syntax and Examples
Core syntax
malloc and free
#include <cstdlib>
int* p = (int*)std::malloc(sizeof(int));
if (p != nullptr) {
*p = 10;
std::free(p);
}
new and delete
int* p = new int(10);
delete p;
Arrays
int* numbers = new int[5];
delete[] numbers;
Example with a class
#include <iostream>
{
:
() {
std::cout << ;
}
~() {
std::cout << ;
}
};
{
User* u = ();
u;
}
Step by Step Execution
Consider this example:
#include <iostream>
class Box {
public:
Box() {
std::cout << "Constructor\n";
}
~Box() {
std::cout << "Destructor\n";
}
};
int main() {
Box* b = new Box();
delete b;
}
Step by step
new Box()requests enough memory for oneBox.- That memory is allocated.
- The
Boxconstructor runs. - The pointer is stored in
b. delete bis executed.- The
Boxdestructor runs. - The memory is released.
Output:
Constructor
Destructor
Now compare with malloc:
Real World Use Cases
When new/delete might be used
Although modern C++ often wraps dynamic memory, raw new may still appear in:
- legacy C++ codebases
- low-level libraries
- custom data structures written for learning or performance work
- code that transfers ownership into another API
Example:
Node* node = new Node(value);
// later
delete node;
When malloc/free might be used
These are more common in special situations:
- calling a C library that expects memory from
malloc - working with raw byte buffers
- implementing custom allocators or memory pools
- interfacing with operating-system or network APIs using plain buffers
Example:
char* buffer = (char*)std::malloc(1024);
if (buffer) {
// fill buffer
std::free(buffer);
}
What is more common in real applications
Real Codebase Usage
In real C++ projects, experienced developers usually follow these patterns:
1. Prefer stack allocation first
If an object does not need dynamic lifetime, create it directly.
User user;
This is simpler and safer than:
User* user = new User();
delete user;
2. Prefer containers over manual arrays
Instead of:
int* values = new int[100];
delete[] values;
Use:
std::vector<int> values(100);
3. Prefer smart pointers over raw ownership
Instead of:
Widget* w = new Widget();
delete w;
Use:
auto w = std::<Widget>();
Common Mistakes
1. Mixing allocation and deallocation styles
Broken code:
int* p = new int(5);
std::free(p); // wrong
int* p = (int*)std::malloc(sizeof(int));
delete p; // wrong
Fix
newpairs withdeletenew[]pairs withdelete[]mallocpairs withfree
2. Using malloc for objects with constructors
Broken code:
MyClass* obj = (MyClass*)std::malloc(sizeof(MyClass));
This does not call the constructor.
Fix
Comparisons
| Concept | malloc / free | new / delete |
|---|---|---|
| Language origin | C | C++ |
| Allocates memory | Yes | Yes |
| Calls constructor | No | Yes |
| Calls destructor | No | Yes |
| Returns typed pointer | No, returns void* | Yes |
| Needs cast in C++ | Usually yes | No |
| Array support | Manual size handling | / |
Cheat Sheet
Quick rules
- Prefer plain objects when possible.
- Prefer
std::vector,std::string, and other standard containers. - Prefer
std::unique_ptrover rawnew. - Use
newfor C++ objects only when manual dynamic allocation is truly necessary. - Use
mallocmainly for C interoperability or raw byte buffers. - Never mix allocation and deallocation families.
Pairing rules
T* p = new T();
delete p;
T* arr = new T[10];
delete[] arr;
void* p = std::malloc(100);
std::free(p);
Important differences
mallocdoes not call constructorsfreedoes not call destructors
FAQ
Should I ever use malloc in modern C++?
Usually no for normal application code. Use it mainly when working with C libraries or raw memory buffers.
Is new better than malloc in C++?
For creating C++ objects, yes. new constructs objects properly, while malloc only allocates raw memory.
Should I use new and delete directly in modern C++?
Usually not. Prefer stack allocation, containers, and smart pointers.
Why is mixing new with free undefined behavior?
Because the allocation and cleanup mechanisms are different. free does not know how to destroy objects created by new.
What should I use instead of new[] for arrays?
Usually std::vector.
What happens if new cannot allocate memory?
By default, it throws std::bad_alloc.
Mini Project
Description
Build a small C++ program that manages a list of scores. The goal is to practice choosing the right memory-management tool and to see why standard containers are usually better than manual allocation. This project demonstrates dynamic storage without needing malloc or raw new[].
Goal
Create a program that stores, prints, and averages a user-defined number of scores using std::vector instead of manual memory management.
Requirements
- Ask the user how many scores they want to enter.
- Store the scores in a dynamically sized container.
- Print all entered scores.
- Calculate and print the average score.
- Do not use
malloc,free,new, ordeletein the final solution.
Keep learning
Related questions
Advantages of Brace Initialization in C++
Learn why C++ brace initialization is often clearer and safer than other object initialization styles, with examples and common pitfalls.
Basic Rules and Idioms for Operator Overloading in C++
Learn the core rules, syntax, and common idioms for operator overloading in C++, including member vs non-member operators.
C++ Aggregates, Trivial Types, Trivially Copyable Types, and PODs Explained
Learn what aggregates, trivial types, trivially copyable types, and PODs mean in C++, how they differ, and why they matter.